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".
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With