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:


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!