Question

I am working on creating an immutable class.
I have marked all the properties as read-only.

I have a list of items in the class.
Although if the property is read-only the list can be modified.

Exposing the IEnumerable of the list makes it immutable.
I wanted to know what is the basic rules one has to follow to make a class immutable ?

Was it helpful?

Solution

I think you're on the right track -

  • all information injected into the class should be supplied in the constructor
  • all properties should be getters only
  • if a collection (or Array) is passed into the constructor, it should be copied to keep the caller from modifying it later
  • if you're going to return your collection, either return a copy or a read-only version (for example, using ArrayList.ReadOnly or similar - you can combine this with the previous point and store a read-only copy to be returned when callers access it), return an enumerator, or use some other method/property that allows read-only access into the collection
  • keep in mind that you still may have the appearance of a mutable class if any of your members are mutable - if this is the case, you should copy away whatever state you will want to retain and avoid returning entire mutable objects, unless you copy them before giving them back to the caller - another option is to return only immutable "sections" of the mutable object - thanks to @Brian Rasmussen for encouraging me to expand this point

OTHER TIPS

To be immutable, all your properties and fields should be readonly. And the items in any list should themselves be immutable.

You can make a readonly list property as follows:

public class MyClass
{
    public MyClass(..., IList<MyType> items)
    {
        ...
        _myReadOnlyList = new List<MyType>(items).AsReadOnly();
    }

    public IList<MyType> MyReadOnlyList
    {
        get { return _myReadOnlyList; }
    }
    private IList<MyType> _myReadOnlyList

}

Also, keep in mind that:

public readonly object[] MyObjects;

is not immutable even if it's marked with readonly keyword. You can still change individual array references/values by index accessor.

Use the ReadOnlyCollection class. It's situated in the System.Collections.ObjectModel namespace.

On anything that returns your list (or in the constructor), set the list as a read-only collection.

using System.Collections.ObjectModel;

...

public MyClass(..., List<ListItemType> theList, ...)
{
    ...
    this.myListItemCollection= theList.AsReadOnly();
    ...
}

public ReadOnlyCollection<ListItemType> ListItems
{
     get { return this.myListItemCollection; }
}

Another option would be to use a visitor pattern instead of exposing any internal collections at all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top