Implicit Cast of Lambda Expression to Custom Class in C# 3.0?

We hit a little speed bump in our work with parameter-less lambdas – we wanted to be able to assign them to objects of a custom class via an implicit cast, this is very important to our cunning plan…

 

To illustrate this consider the following class that just encapsulates a 0-arity delegate Func<T>:

    public class RuleProp<T>
    {
        private Func<T> _lambda = null;
        public RuleProp(Func<T> l)
        {
            _lambda = l;
        }
        public static implicit operator RuleProp<T>(Func<T> l)
        {
            return new RuleProp<T>(l);
        }
        public RuleProp()
        {
        }
    }

Now, because we have specified an implicit cast for: Func<T> -> RuleProp<T>, it would seem  that we should be able to do the following:

var rp = new RuleProp<string>();
rp = () => "hello"; // Not OK, can't convert lambda to delegate 

But this gives us a compiler error, can’t convert lambda to Fun<T> as it’s not a delegate!!  Looking at the C# specification it seems that if more than one implicit conversion is required, the C# compiler will only do one.  In this case 2 conversions are required:

 

Lambda Expression -> Func<T> -> RuleProp<T>

 

And so the compiler can’t handle it.  If we provide an explicit cast to Func<T> it compiles OK:

 

rp = (Func<string>)(() => "hello");  // Cast works..

 

But this is really ugly as the type must be provided each time.  A workaround was suggested in this article:

 

http://www.interact-sw.co.uk/iangblog/2008/03/17/lambda-inference

 

We provide an ‘adaptor’ function which encourages a cast from Lambda -> Func<T>, and the implicit cast from Func<T> to RuleProp<T> will handle the rest, we can use it like this:

 

rp = Adaptor(() => "hello");  // Now OK!

This is much nicer than the explicit cast as no type needs to be specified!  Here is the function, it just take,s and directly returns a delegate – resulting in just the conversion that we need!

 

public static Func<T> Adaptor<T>(Func<T> f)
{
 return f;
}

 

So although it is not as nice as directly assigning a lambda to RuleProp<T> it’s a grand workaround and will do nicely for the time being – thanks to all at the C# MSDN forum for their help!