Immutable objects are very popular in concurrency models because immutable objects are naturally thread safe because the state an object cannot be corrupted by multiple threads. As C# developers we can also benefit from immutability. C# has a keyword just for that, readonly. We can also utilize readonly property mechanism with private setters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
These are all good approaches but they don’t accompany you to the depths of API design hell! From now on, I will approach the notion of immutability from another perspective. Classical definition of immutable object says that the object’s state is not changeable after it has been initialized. I find it valuable to be able to change the state of an object after it has been constructed but only once.
readonly keyword ensures that a field can only be assigned where it is declared or in the relevant constructor(static or instance). What if I want a field to be assigned even after it has been instantiated but ensured to be assigned only once?
Readonly properties are phenomenal, I use them everywhere appropriate. But they too don’t solve the problem. Take a look at the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Readonly property mechanism fails you here, because both the private setter and the backing field is always there to change the state of the object.
What do we do now? We can add an extra boolean field that keeps track of the assignment. But then if you have 5 fields that should be assigned only once, you have to add 5 extra fields to back them up and it would clutter the class definition.
I’ve defined a very basic generic type called WriteOnce
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
|
WriteOnce ensures that as the developer of a class, you assign a field only once. If you plan to enable users assign values to fields but again only once, you can do that too. Now using this type I can define the previous class like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|