Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda treated as a closed delegate in Roslyn

I was surprised that there would be any runtime difference between these two delegates (fn1 and fn2):

static int SomeStaticMethod(int x) { return x; }

// fn1.Target == null in this case
Func<int, int> fn1 = SomeStaticMethod;

// fn2.Target != null in this case
Func<int, int> fn2 = x => x;

But apparently the second lambda is treated like an instance method, because its Target property is non-null. And it was treated differently before I switched to Visual Studio 2015 (in VS2012, I am pretty sure it was treated as a static method).

Is there a reason why a lambda with no closures is treated as a closed delegate (i.e. an instance method) in C#? I thought perhaps it's the debugger adding some stuff, but it also happens in release builds.

(Clarification)

The point is, I had a method like this which created a generic delegate for quickly converting from enums to ints (without boxing):

private static Func<int, TEnum> CreateIntToEnumDelegate()
{
    Func<int, int> lambda = x => x;
    return Delegate.CreateDelegate(typeof(Func<int, TEnum>), lambda.Method) 
        as Func<int, TEnum>;
}

and it didn't work in Roslyn anymore, because the "instance" lambda became incompatible with the delegate signature. So I had to use a static method instead, no big deal.

But what worries me is that this was impossible to catch during compile-time. This thread describes similar issues, btw, now that I searched for "Roslyn delegates".

like image 200
Groo Avatar asked Sep 27 '22 02:09

Groo


1 Answers

This was a change made to Roslyn in 2014. It is quite strange, but it was actually done to improve performance. "In the new strategy all lambdas are emitted as instance methods" - from the discussion at roslyn.codeplex.com (note: dead link).

like image 86
Galax Avatar answered Sep 29 '22 08:09

Galax