Immutability In C#
I’ve struggled with how to allow immutable objects in object-oriented languages like C#, Java, and C++, either at the application level or with new language features. Here are a few thoughts.
It’s not so clear that immutable instances should be created in the constructor. For example, if an application has a complicated List<T>
instance, how is this going to get created in a List<T>
constructor? In general, if you want to build up a value and then declare it immutable, you have to make the constructor accept all possible state. One way, maybe the only way, to do that in a general way is to make a constructor or constructor-like method that accepts another instance of the same type and, from that instance, constructs an immutable instance. It may be that doing this in a thread-safe way requires something like calling Thread.MemoryBarrier()
(System.Threading
namespace) upon completion of construction. This will incur a significant performance penalty. If this call is made from automatically generated code, then many users will construct immutable objects without knowing about the penalty. Possibly the CLR could do it without the penalty.
Multi-type solutions seem very bad. They cause impedance mismatches – the same thing that happens in C++ when you try to call a non-const-ful method from a const-ful one. In C++ there are essentially two disjoint families or methods: those that have const arguments, and those that don’t. Practically, the two families do not work well with each other, and aesthetically, it’s irritating that there are two families in the first place. If you have one type for mutable instances and another for non-mutable, a smiilar problem arises. Multi-type solutions to immutability are non-polymorphic. For example, with String and StringBuilder, the only way to write a method that accepts an instance that could be either a String or a StringBuilder instance is to make a method that accepts an Object instance. Writing a method or collection of methods to deal with strings involves another two-family problem. You essentially have to decide whether you want to orient the methods towards String, or towards StringBuilder. This is not very pleasant. At least it’s better than having MutableString derive from ImmutableString, or vice versa.
After many design iterations, I’m now wondering if what’s needed is one bit for each object saying whether the instance is immutable. Possibly another bit or so could be used to say whether the instance is ‘read only’ in the sense returned by the List<T>.AsReadOnly
method (System.Collections.Generic
namespace). I have been using two such bits at the application level in my own library, and the system seems to be manageable.
If you want to allow semantics similar to copy-on-write, you might find the following enumeration helpful.
public enum AccessorIdentity : byte
{
Us
, Unknown
, Nobody
}
Posted on May 7th, 2008 by Andrew
Under C# / Common Language Infrastructure, Programming | No Comments »