Nerdy tidbits from my life as a software engineer

Wednesday, December 10, 2008

Private Set Instead of Readonly

Is there any reason you would rather declare

public readonly string SomeValue;

…instead of…

public string SomeValue
    private set;

From what I can see, in most cases, you’re better of having the private set (a 3.5 and above feature, admittedly).  Readonly certainly makes sense for constants, though my feeling is that you’re better of declaring those variables const instead of readonly in most of those cases.  In other words,

public readonly string SOME_STRING = "Some String";

is less preferable than:

public const string SOME_STRING = "Some String";

The reason being that any simple constant can be determined at compile time, whereas readonly values are determined at run time.  You can even give a quick scan to the IL produced by those two statements and see the difference yourself.  What you’ll see is that using readonly will cause the compiler to shove this into the IL of your constructor:

IL_0000:  ldarg.0
IL_0001:  ldstr      "Some String"

Where as using const will simply insert the assignment statement into the .field declaration:

.field public static literal string SOME_STRING = "Some String"

In other words, the first option will run for all instances of your class, whereas the second option will run when the object is loaded onto the heap (it also allows you to access the value of fields using reflection, which has other uses).  So, why use readonly at all?  Well, you can’t do this using const:

public const Object SOME_OBJECT = new Object();

Because consts can’t be instance objects.  This is really why we have the readonly keyword, because it lets you do this:

public readonly Object SOME_OBJECT = new Object();

Which does admittedly have some value.  But the problem with this code is that you’re exposing public member variables instead of public properties.  This really is a cardinal sin, in my opinion, because you are explicitly giving up one of the most important features of object orientated programming: encapsulation.  Properties allow you to get the convenient syntax you’re looking for without sacrificing the benefits of abstraction.  If you ever wanted to refactor your code so that SOME_OBJECT did some sort of funky logic, or if you ever started adding subclasses and create a hierarchy, you’d be stuck because you chose to make SOME_OBJECT a public member variable instead of a property with a private set.

I see plenty of value in having private readonly variables – but anything that is exposed to the rest of the world should really be encapsulated in a property.  Otherwise, make it const.

UPDATE: It’s occurred to me that there is one useful place to use readonly, and that is when declaring static readonly fields.  This actually can make life a little bit easier, because doing it using properties would usually require quite a bit of extra code to just about the same thing.  You could easily author a few static properties, add a static constructor, and accomplish more or less the same thing that happens when you declare a static readonly field.  Of course, you’re still accessing the value via a public field, which I think is less preferable to a public property.  But as long as it’s readonly, I don’t think you’re really violating any terrible design principles.