Jun 26 2008

Readonly is in the eye of the beholder

Category: .NetRory Primrose @ 06:11

One of my most used feature in the 3.5 compiler for .Net is automatic properties. In case you are not familiar, here is a recap.

Traditionally, properties work with a backing field. For example:

private String _someValue;

public String SomeValue
{
    get
    {
        return _someValue;
    }
    set
    {
        _someValue = value;
    }
}

Automatic properties under the 3.5 compiler allow this code to be represented as:

public String SomeValue
{
    get;
    set;
}

Automatic properties make code cleaner and easier to use. Additionally, they also require less testing. There isn't any point testing their logic of accessing the backing field to ensure correct operation and they appear with 100% code coverage. My biggest gripe though is that they don't truly support readonly definitions.

The documentation on MSDN says:

Auto-implemented properties must declare both a get and a set accessor. To create a readonly auto-implemented property, give it a private set accessor.

The implementation of automatic properties by the compiler define that readonly automatic properties are achieved by assigning a private scope to the set accessor. For example:

public String SomeValue
{
    get;
    private set;
}

Unfortunately, I think this is a cheap bandaid hack. It doesn't make the property truly readonly. It is technically readonly, but only from the perspective of external callers. Internal to the class, the property is not readonly because the private scope makes setting the property value possible. This doesn't protect the value of the backing field which is what a true readonly property should be able to support. See here for the MSDN documentation on the readonly keyword.

I would like to see this changed. Without understanding the complexities of writing compilers, I would think that this change would not be too significant. The simple fix would be to enhance the syntax of the automatic property setter definition. If the private set statement could be enhanced to understand a readonly keyword, then the compile could mark the backing field with the same readonly keyword. For example:

public String SomeValue
{
    get;
    private readonly set;
}

This would then be interpreted by the compiler as something like this:

private readonly String _someValue;

public String SomeValue
{
    get
    {
        return _someValue;
    }
    set
    {
        _someValue = value;
    }
}

I have added this as a suggestion to Microsoft Connect here.

Tags:

Comments

1.
Eddie Eddie says:

Hey Rory,

I have to agree with you here, except for one thing which I honestly must say I don't understand (becuase I haven't taken the time to look into it too much..)..

Basically, how does all this work with WCF? For WCF to do it's bits, it requires a public Get/Set with the DataMemeber attribute. Failing that, you can force it to use the backing variable. Automatic properties remove the ability to have the backing variable as the DataMember. Becuase of this, I presumed that the restriction on having the set was to overcome this sort of situation..

Any thoughts?

2.
Rory Primrose Rory Primrose says:

Hi Eddie,

Yep you are right. In order for the DataContractSerializer to do its work, it should require access to both the getter and setter. My suggestion here isn't related to WCF however. It is more a general comment regarding the current c# standard and the 3.5 compiler.

The usage of a true readonly automatic property is only relevant to classes that accept constructor parameters which are expressed as properties that only expose a get accessor where the class instance after construction is also not allowed to change the property value.

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading