No programming language is perfect. In spite of the many strengths of C#, there are still a few gaping holes, including generics variance and property delegates.
A delegate is a reference to a method. Unfortunately, C# currently does not support property delegates, in other words, a reference to a property. But there are a few workarounds, one of which involves anonymous methods.
An anonymous method is a new feature in C# 2.0 that enables you to define an anonymous (nameless) method called by a delegate. Anonymous methods are perfect when there is no need for multiple targets, and the code is relatively short and simple. They also come in handy when you need a delegate to a property.
Consider this simple example of a Person class. For demo purposes, the Person class contains both a Name property and explicit GetName() and SetName() methods:
public class Person { public Person() { } public Person( string name ) { this.m_Name = name; } private string m_Name; public string Name { get { return this.m_Name; } set { this.m_Name = value; } } public string GetName() { return this.m_Name; } public void SetName( string name ) { this.m_Name = name; } }
In this console program, there is a GetSalutation() method that accepts a delegate instead of a string. Specifically, it accepts a GetStringCallback delegate that itself returns a string:
class Program { static void Main( string[] args ) { Person joe = new Person( "Joe" ); string dearJoe = GetSalutation( new GetStringCallback( joe.GetName ) ); Console.WriteLine( dearJoe ); dearJoe = GetSalutation( new GetStringCallback( joe.Name ) ); Console.WriteLine( dearJoe ); Console.ReadLine(); } static public string GetSalutation( GetStringCallback callback ) { return String.Format( "Dear {0},", callback() ); } public delegate string GetStringCallback(); }
In the Main method, we create a Person object for “Joe”. Then we call the GetSalutation method using a GetStringCallback delegate that references the GetName method on Joe’s Person object. So far so good.
But two lines later when we attempt to use a GetStringCallback delegate that references the Name property on Joe’s Person object, the compiler complains with the error:
‘Person.Name’ is a ‘property’ but is used like a ‘method’
This error occurs because C# does not support property delegates. But in place of the property delegate, you can create an anonymous method that returns the property value:
dearJoe = GetSalutation( delegate() { return joe.Name; } );
This will compile cleanly and work fine, essentially providing a delegate to a property. Note that you have to be aware of scoping issues. For example, since Joe’s Person object is defined locally in the Main() method, you want to ensure the delegate is executed in the Main method’s scope while the Joe object is still valid.
Anonymous methods are defined in-line and not as a member of any class. Also, there is no way to apply attributes, define generic types or add generic constraints to an anonymous method (though you can use generic types defined at the class level). But as you can see here, anonymous methods work great as property delegates. You can read more about anonymous methods in MSDN Magazine.
Any idea if property delegates are supported in C# 3.0? And if not, whether new workarounds are possible?
To my knowledge, C# v3.5 does not support property delegates as a language feature, hence a workaround (like the one above) is still required.
Some really usefull information here if you pay attention, thanks
Excuse the formatting. No reasonable expectation that the results will be readable, but I do the best I can.
public static Func GetPropertyDelegate
(object obj, string name)
{
return FuncDelegate.CreateDelegate(typeof(Func),obj,methodName);
}
Not typesafe, but when you actually need a property delegate it makes do.
This would be about #3 on my list of shocking laziness on the part of c# designers.
Expectations exceeded. Second try:
public static Func<T> GetPropertyDelegate
(object obj, string name)
{
return (Func<T>) Delegate.CreateDelegate(typeof(Func<T>),obj,methodName);
}
@Ed Rowland:
In C# 3.0 if you want to make a delegate that obtains a property value, all you have to say is:
() => person.FirstName;
For example:
Func<string> getter = () => person.FirstName;
Console.WriteLine(getter());
Similarly to capture the setter:
Action<string> setter = v => person.FirstName = v;
Lambda syntax is so succinct that it makes many common scenarios very readable without the need for dozens of special syntaxes.
I think the real lazy people are those who don’t bother to learn about the various things the C# designers got right! 🙂
@Daniel Earwicker
What you write is true, but off the mark. I think what they’re looking for is delegate for a property, not a delegate that uses a property. Something that captures both the getter and setter. For example, to bind the delegated property to a control.