Saturday, February 23, 2008

Enhanced Automatic Properties

Recently there's been a lot of blog posts discussing things people would like to see in the next version of C#. Here's my addition to the wish-list:

"Automatic properties that let me supply a method body." It sounds like a contradiction in terms - but it doesn't have to be. Instead, it would be a compact syntax for defining properties that use standardised method bodies (where you define your own "standard" bodies).

Some places where it would be useful:
  1. Cases where many properties follow a standard format.  For instance, all the properties generated by the LINQ designer could be single-line automatic properties.  (Much less verbose than the current approach).
  2. ORM's and similar products that require properties to be written according to certain conventions.  (E.g. Mindscape LightSpeed)
How would it look?

Right now, we can write automatic properties like this:
public int Foo { get; set; }
My suggestion is that the words "get" and "set" could be replaced by the names of methods. For instance:
public int AdvancedFoo { GetValue; SetValue; }


Where the methods "GetValue" and "SetValue" are generic instance methods with these signatures:
/// <summary>
/// When passed the field, return the property value
/// </summary>
T GetValue<T>(ref T field)
{
// ... your own code goes here...
}

/// <summary>
/// When passed the field, by ref, and the new property value, set the field
// </summary>
void SetValue<T>(ref T field, T value)
{
//...your own code goes here...
}
Given the above property, "AdvancedFoo", the compiler would compile it as if I had written this:
public int AdvancedFoo
{
get { return GetValue(ref _advancedFoo); }
set { SetValue( ref _advancedFoo, value); }
}

private int _advancedFoo; // compiler-generated backing field
Just as in today's automatic properties, the compiler would generate the backing field for me. The difference is that it reads and writes that backing field via methods which I define.

This goes a long way towards giving the best of both worlds: the compact syntax of automatic properties, and the flexibility of my own code (plus standardisation - all me properties that are supposed to work the same way do work the same way, because they all use the same code).

Questions:

Why does the "GetValue" method take the field "by ref"? SetValue needs it by ref, but why GetValue? GetValue takes it by ref simply so that you can use this trick to find out which property is being read - just in case you need to know. This is something you are more likely to need to know when setting, e.g. to raise change notificiations, but maybe some people want to identify the property in GetValue too. Using the ref param makes that possible.

What type should the complier use for the backing field? Simply put, it should use whatever field type is implied by the field parameters of the "GetValue" and "SetValue" methods. E.g. an automatic property for a LINQ EntityRef might look like this:
T GetEntity(ref EntityRef<T> field) where T:class
{}

void SetEntity(ref EntityRef<T> field, T value) where T:class
{}
allowing me to write this:
public Customer Bar{ GetEntity; SetEntity; }
and have the compiler compile it as if I had written this:
public Customer Bar
{
get { return GetEntity(ref _bar);}
set { SetEntity(ref _bar, value);}
}
private EntitySet<Customer> _bar;

Note that the compiler is able to infer that the backing field should be EntitySet, not Customer, based on the signatures of Get/SetEntity.

(And how would Get/SetEntity actually work? That's a question for another day ;-) I do have some (working) prototype code...)

What do you think of this idea for enhanced automatic properties?

Update 2 March: posted on MS Connect here (in the comments)

Update 12 March: And here here as an MS Connect item in its own right.

1 Comments:

Anonymous Mike said...

I am working on doing simalar things using AOP and PostSharp.

http://www.postsharp.org/

Tue Apr 29, 12:12:00 PM PDT  

Links to this post:

Create a Link

<< Home