16 October 2007

C# 3.0 Automatic Properties - Incomplete Feature?

Well, C# 3.0 is nice language. However, digging into details of every new language feature while developing ReSharper support make me wonder about little things that look like incompleteness. Today I'm going to wonder about automatic properties.

public string Name { get; set; }

This code is correct in C# 3.0, there are no missing "abstract" or get/set bodies. It simply means that compiler will create field and accessors code for you:

private string __someGeneratedFieldName;
 
public string Name
{
  get { return __someGeneratedFieldName; }
  set { __someGeneratedFieldName = value; }
}


What is cool about automatic properties? Obviously, ReSharper users don't benefit much from shorter code - who types properties by hand these days? However there is one very important thing:

Less complexity to manage.

If you want to know how this property gets its value, you no longer need to search for both field and property usages. You don't need to synchronize field and property types, once you decide to change it. Also, access to the class attribute (in OOP sense) is fully controlled right at the place of the declaration. You can limit it as you wish:

public string Name { get; private set; }

This way you declare that "Name" can be modified only within the class itself, but can be read from outside.

So, what is missing from this language feature?

Initializer.
I may wish to initilize property to some non-default value. Like this:

public List<Person> Persons { get; private set; } = new List<Person>();

Read-only automatic property
In the example above, I don't actually need setter.

public List<Person> Persons { get; } = new List<Person>();

Obviously, you don't need read-only automatic property without initializer. Also note, that such property can never change its value, even in constructor, unlike readonly fields.

Attributes on generated fields
If you use simple event form and compiler generates field for storing delegate, you can apply attribute to the generated field by using attribute target:

[field: NonSerialized]
public event EventHandler Closed;

I wish I could do the same with automatic properties:

[field: NonSerialized]
public List<Person> Persons { get; } = new List<Person>();


Conclusion
Few simple improvements over existing implementation could make automatic properties much more useful in everyday professional .NET development. Unfortunately, language designers decided:
they would work in the "common case" which among other things means no attributes on the generated field. The idea behind that is keeping them simple and not slowly mutating them into full properties.

I'd prefer the advanced version, if I had a chance to choose.