ReadonlyCollection, are the objects immutable? - c#

I'm trying using ReadOnlyCollection to make object immutable, I want the property of object are immutable.
public ReadOnlyCollection<FooObject> MyReadOnlyList
{
get
{
return new ReadOnlyCollection<FooObject>(_myDataList);
}
}
But I little confused.
I tried to change the property of the object in to MyReadOnlyList using a foreach and ... I can change value property, is it correct? I understood ReadOnlyCollection set an add level to make the object immutable.

The fact that ReadOnlyCollection is immutable means that the collection cannot be modified, i.e. no objects can be added or removed from the collection. This does not mean that the objects it contains immutable.
This article by Eric Lippert, explains how different kinds of immutability work. Basically, a ReadOnlyCollection is an immutable facade which can read the underlying collection (_myDataList), but cannot modify it. However, you can still change the underlying collection since you have a reference to _myDataList by doing something like _myDataList[0] = null.
Furthermore, the objects returned by ReadOnlyCollection are the same ones returned by _myDataList, i.e. this._myDataList.First() == this.MyReadOnlyList.First() (with LINQ). This means that if an object in _myDataList is mutable, then so is the object in MyReadOnlyList.
If you want the objects to be immutable, you should design them accordingly. For instance, you might use:
public struct Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
// In C#6, the "private set;" can be removed
public int X { get; private set; }
public int Y { get; private set; }
}
instead of:
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
}
Edit: in this case, as noted by Ian Goldby, neither struct allows you to modify properties of the elements in the collection. This happens because structs are value types and when you access an element the collection returns a copy of the value. You can only modify the properties of a Point type if it is a class, which would mean that references to the actual objects are returned, instead of copies of their values.

I tried to change the property of the object in to MyReadOnlyList
using a foreach and ... I can change value property, is it correct? I
understood ReadOnlyCollection set an add level to make the object
immutable.
Using a ReadOnlyCollection does not make any guarantees as for the object that is stored in the collection. All it guarantees is that the collection cannot be modified once it has been created. If an element is retrieved from it, and it has mutable properties, it can very well be modified.
If you want to make your FooObject an immutable one, then simply do so:
public class FooObject
{
public FooObject(string someString, int someInt)
{
SomeString = someString;
SomeInt = someInt;
}
public string SomeString { get; };
public int SomeInt { get; };
}

What is immutable is the collection itself, not the objects. For now, C# doesn't support immutable objects without wrapping them as ReadOnlyCollection<T> does in your case.
Well, you can still create immutable objects if their properties have no accessible setter. BTW, they're not immutable at all because they can mutate from a class member that may have equal or more accessibility than the setter.
// Case 1
public class A
{
public string Name { get; private set; }
public void DoStuff()
{
Name = "Whatever";
}
}
// Case 2
public class A
{
// This property will be settable unless the code accessing it
// lives outside the assembly where A is contained...
public string Name { get; internal set; }
}
// Case 3
public class A
{
// This property will be settable in derived classes...
public string Name { get; protected set; }
}
// Case 4: readonly fields is the nearest way to design an immutable object
public class A
{
public readonly string Text = "Hello world";
}
As I said before, reference types are always mutable by definition and they can behave as immutable under certain conditions playing with member accessibility.
Finally, structs are immutable but they're value types and they shouldn't be used just because they can represent immutable data. See this Q&A to learn more about why structs are immutable: Why are C# structs immutable?

Related

C# Should I make a second class for single properties when my first class has an object array?

So basically I have this one class called Animal.
In this class I have strings a,b,c,x,y,z;
I want to make an object array for this program so I make one called arr.
For a,b,c,x and y I want to have different values for each object array elements.
I.e.: arr[0].a will be different than arr[1].a, which is different than arr[2].a etc.
However, for the property z, I only want to use one value for the whole of the program, I.e: arr[0].z is the only z value that I want to use. Currently I just call arr[0].z and never use any other number in [].
Is this bad practice and should I make a whole new class, just for property z so that I don't waste memory space? Are there any other problems associated with not using any of the other values of z?
Make the z variable static and in the constructor of you class simply initialize with this value.
You can implement your class in this way.
public class Animal
{
public string A { get; } // related to instance
public string B { get; }
public string C { get; }
public string X { get; }
public string Y { get; }
public string Z // gets or sets static variable which will affect all animals.
{
get { return _z; }
set { _z = value; }
}
private static string _z;
}
Is this bad practice ?
Without context we cant say its always bad design or not. But generally, yes its bad design.

Accessing Field from derived Class

I'm trying to access a field from a derived class in an array that holds references to the base class.
I have three classes:
abstract GameObjectBase
{
}
And derived from that are:
public Gamespace: GameObjectBase
{
private bool containsItem;
}
And:
public GameWall: GameObjectBase
{
}
(Obviously these classes hold more data, methods, and constructors).
I have created an array from these objects, like this
private GameObjectBase[,] _labyrinthArray = new GameObjectBase[10,10];
I then fill said array with Gamespaces and Gamewalls. But when I access a Gamespace object in the array, the containsItem field is not accessible due to the reference to the object being of type GameObjectBase.
Obviously I could put containsItem in GameObjectBase and make it accessible from there, but that doesn't fit my OOP approach. The only other solution I have found is to cast the object in question explicitely to Gamespace.
That seems quite crude and error prone to me. Is there any better solution to this?
First of all, you cannot reference a private field from outside the object class itself. You probably want to use a read-only property to encapsulate the field. If you don't want to cast the object explicitly to a Gamespace, you could use an interface instead.
public interface ICanContainItem
{
bool ContainsItem { get; }
}
public class Gamespace : GameObjectBase, ICanContainItem
{
private bool _containsItem;
public bool ContainsItem
{
get { return _containsItem; }
private set { _containsItem = value; }
}
}
This way you can then check whether the object "can contain an item" or not through the interface. Even if in the future you add new types of spaces that can contain an item, this same piece of code works, if the new types also implement the same interface.
var gameObject = _labyrinthArray[i,j]; //i,j defined elsewhere
var mayContainItem = gameObject as ICanContainItem;
if (mayContainItem != null)
{
var itemExists = mayContainItem.ContainsItem;
//mayContainItem.ContainsItem = false; //<-- fails because there's no setter
}

Prevent dictionary from modifications

How do I prevent dictionary items from modification outside of my class?
I have to expose collection of objects as a property, but then everyone can do everything with my objects. I tried to use ReadOnlyDictionary to wrap my public property, but IntegerValue property still can be modified from outside.
Sample code is below:
internal class MyRefClass
{
public object ReferenceStrig;
public int IntegerValue;
public MyRefClass()
{
ReferenceStrig = "Initialized string";
IntegerValue = 100;
}
}
class Program
{
static void Main(string[] args)
{
var writableDict = new Dictionary<int, MyRefClass>();
writableDict.Add(1,new MyRefClass());
ReadOnlyDictionary<int, MyRefClass> dict = new ReadOnlyDictionary<int, MyRefClass>(writableDict);
MyRefClass variable;
dict.TryGetValue(1, out variable); #get an object from dictionary
variable.IntegerValue = 0; #changing property of the object
writableDict.TryGetValue(1, out variable); #get the same object once again
#now property variable.IntegerValue == 0 instead of 100!
}
}
If you want to expose an object to "Client code" and yet you want the object not to be modified then you must return a "Immutable type". Either in the form of immutable class or an interface with only readonly properties.
This also means that all the properties and nested properties and so on of your type should also be "Immutable" otheriwse they will be still able to modify the nested members. In other words All types in object graph of the type you expose must be Immutable.
Another option is to clone the object and return the copy and forget about the modifications. But be sure you're doing a Deep-Copy and not Shallow-Copy. Shallow copy suffers from aforementioned problem.
Make your class immutable, for example:
class MyImmutableRefClass
{
public readonly object ReferenceStrig;
public readonly int IntegerValue;
public MyImmutableRefClass(): this("Initialized string", 100)
{
}
public MyImmutableRefClass(string referenceStrig, int integerValue)
{
ReferenceStrig = referenceStrig;
IntegerValue = integerValue;
}
}
This isn't really enough if ReferenceStrig is an object which itself isn't immutable. It works for this particular example because it can only be a string (which is itself immutable).
But if it was some other type, then that type would have to be immutable itself - and (recursively) any public fields and properties that it contains would also have to be immutable. (I call that "deep-immutable".)
Here's an interesting series of articles on immutability in C#:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx

Keep old object without changing it

I have the following code and In RT when mappingObject is updated oldObjToDel is updated accordingly, but my question is :
Is there a way to keep the oldObjToDel with the first reference without changing it like it happens after calling to the updateReferance method ? I want oldObjToDel to keep the object before changing it in UpdateReferance...
private bool UpdateMapping(out MappingFields oldObjToDel)
{
MappingFields mappingObject = GetMappingLabelObject(textbox.Name);
oldObjToDel = mappingObject;
isAdded = UpdateReferance( mappingObject);
}
internal class MappingFields
{
public string Type { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public bool isFound { get; set; }
}
There is no way to do this automatically in the general case. You need to make a copy (clone) of the object, which would be independent of its "source".
If your object only has scalar fields then you can utilize object.MemberwiseClone; otherwise, you should consider implementing ICloneable and supply an implementation of Clone with appropriate semantics. The documentation for MemberwiseClone also lists several alternatives:
There are numerous ways to implement a deep copy operation if the
shallow copy operation performed by the MemberwiseClone method does
not meet your needs. These include the following:
Call a class
constructor of the object to be copied to create a second object with
property values taken from the first object. This assumes that the
values of an object are entirely defined by its class constructor.
Call the MemberwiseClone method to create a shallow copy of an object,
and then assign new objects whose values are the same as the original
object to any properties or fields whose values are reference types.
The DeepCopy method in the example illustrates this approach.
Serialize the object to be deep copied, and then restore the
serialized data to a different object variable.
Use reflection with
recursion to perform the deep copy operation.
Update:
Since your implementation of MappingFields only uses string and boolean fields, MemberwiseClone will do the job. First expose a Clone method:
internal class MappingFields : ICloneable
{
public string Type { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public bool isFound { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
and then call it:
oldObjToDel = (MappingFields)mappingObject.Clone();
You could use AutoMapper to create a clone of the original object easily. I guess this post could give some idea on how to do it. You could also check AutoMapper getting started page.
Hope I helped!

How can I set the value of auto property backing fields in a struct constructor?

Given a struct like this:
public struct SomeStruct
{
public SomeStruct(String stringProperty, Int32 intProperty)
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
public String StringProperty { get; set; }
public Int32 IntProperty { get; set; }
}
Of course, a compiler error is generated that reads The 'this' object cannot be used before all of its fields are assigned to.
Is there a way to assign values to the backing fields or the properties themselves, or do I have to implement properties the old-fashioned way with my own explicit backing fields?
Prior to C# 6, you need to use the "this" constructor in this scenario:
public SomeStruct(String stringProperty, Int32 intProperty) : this()
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
Doing this calls the default constructor and by doing so, it initializes all the fields, thus allowing this to be referenced in the custom constructor.
Edit: until C# 6, when this started being legal; however, these days it would be much better as a readonly struct:
public readonly struct SomeStruct
{
public SomeStruct(string stringProperty, int intProperty)
{
this.StringProperty = stringProperty;
this.IntProperty = intProperty;
}
public string StringProperty { get; }
public int IntProperty { get; }
}
If a structure is going to have, and its users will expect it to have, all three of the following characteristics:
Its entire state is encapsulated in some particular fixed set of readable members
An instance may be readily created in which those members have any combination of values which are valid for their respective types.
A default instance of the type should have all of those members set to the default values of their respective types.
the type should expose its members as fields. The above requirements mean a struct won't be able to do anything an exposed-field struct can't do, and will also mean that if code doesn't hit any threading hazards the struct will be able to do anything an exposed-field struct can do, albeit perhaps more slowly and with more threading hazards.
If a struct Foo has fields f1 and f2, and a constructor which sets those fields in that order, and if fooExpr is some sort of expression of type Foo [perhaps a variable, field, array reference, property, or whatever] the statement:
myFoo.f2 = someValue;
will only be allowed in cases where one could legally say
myFoo = new Foo(myFoo.f1, someValue);
and in all circumstances where the first form is allowed and the behavior of the second form has defined semantics, they will behave identically. Thus, trying to "encapsulate" the properties of Foo doesn't really accomplish anything except make the code more cumbersome to write, less clear, and slower to execute.

Categories