TrueWill
TrueWill

Reputation: 25523

Why are lambdas convertible to expressions but method groups are not?

LINQPad example:

void Main()
{
    One(i => PrintInteger(i));
    One(PrintInteger);

    Two(i => PrintInteger(i));
    // Two(PrintInteger); - won't compile
}

static void One(Action<int> a)
{
    a(1);
}

static void Two(Expression<Action<int>> e)
{
    e.Compile()(2);
}

static void PrintInteger(int i)
{
    Console.WriteLine(i);
}

Uncommenting the Two(PrintInteger); line results in an error:

cannot convert from 'method group' to 'System.Linq.Expressions.Expression<System.Action<int>>'

This is similar to Convert Method Group to Expression, but I'm interested in the "why." I understand that Features cost money, time and effort; I'm wondering if there's a more interesting explanation.

Upvotes: 10

Views: 1382

Answers (3)

Nick Butler
Nick Butler

Reputation: 24383

In the One example, you are implicitly creating an Action<int> delegate. It's the same as:

One( new Action<int>( PrintInteger ) );

I believe this is in the language to improve the syntax for subscribing to events.

The same thing doesn't happen for Expression<T>, which is why your second example doesn't compile.


EDIT :

It's called a "method group conversion". It's in the C# spec - section 6.6

An implicit conversion (§6.1) exists from a method group (§7.1) to a compatible delegate type

Upvotes: 0

usr
usr

Reputation: 171178

There is no reason in principle. It could be done this way. The compiler could just create the lambda by itself before converting it (this is obviously always possible - it knows the exact method being called so it can just create a lambda from its parameters).

There is one catch, though. The name of the parameter of your lambda is normally hard-coded into the IL being generated. If there is no lambda, there is no name. But the compiler could either create a dummy name or reuse the names of the method being called (they are always available in the .NET assembly format).

Why didn't the C# team decide to enable this? The only reason that comes to mind is that they wanted to spend their time elsewhere. I applaud them for that decision. I'd rather have LINQ or async than this obscure feature.

Upvotes: 3

Konrad Rudolph
Konrad Rudolph

Reputation: 545488

Because, in order to get the expression tree, we need a representation of the method in (uncompiled) source form. Lambda expressions are locally available in the source code and therefore are always available uncompiled. But methods may not be from inside the current assembly, and may thus be available only in compiled form.

Granted, the C# compiler could decompile the assembly’s IL code to retrieve an expression tree but as you mentioned, implementing feature costs money, this particular feature isn’t trivial, and the benefits are unclear.

Upvotes: 9

Related Questions