Anonymous methods are basically functions without a name, with the ability to create closures. Lambda expressions are constructs that are convertible to both anonymous methods and expression trees, and follow more complex rules of type inference than anonymous methods.
A lambda expression is a block of code (an expression or a statement block) that is treated as an object. It can be passed as an argument to methods, and it can also be returned by method calls. Lambda expression is a shorter way of representing anonymous methods.
Local functions are methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from: Methods, especially iterator methods and async methods.
The => token is supported in two forms: as the lambda operator and as a separator of a member name and the member implementation in an expression body definition.
Why the C# 7 Compiler turns Local Functions into methods within the same class where their parent function is. While for Anonymous Methods (and Lambda Expressions) the compiler generates a nested class for each parent function, that will contain all of its Anonymous Methods as instance methods ?
For example, C# code (Anonymous Method):
internal class AnonymousMethod_Example
{
public void MyFunc(string[] args)
{
var x = 5;
Action act = delegate ()
{
Console.WriteLine(x);
};
act();
}
}
Will produce IL Code (Anonymous Method) similar to:
.class private auto ansi beforefieldinit AnonymousMethod_Example
{
.class nested private auto ansi sealed beforefieldinit '<>c__DisplayClass0_0'
{
.field public int32 x
.method assembly hidebysig instance void '<MyFunc>b__0' () cil managed
{
...
AnonymousMethod_Example/'<>c__DisplayClass0_0'::x
call void [mscorlib]System.Console::WriteLine(int32)
...
}
...
}
...
While this, C# code (Local Function):
internal class LocalFunction_Example
{
public void MyFunc(string[] args)
{
var x = 5;
void DoIt()
{
Console.WriteLine(x);
};
DoIt();
}
}
Will generate IL Code (Local Function) similar to:
.class private auto ansi beforefieldinit LocalFunction_Example
{
.class nested private auto ansi sealed beforefieldinit '<>c__DisplayClass0_0' extends [mscorlib]System.ValueType
{
.field public int32 x
}
.method public hidebysig instance void MyFunc(string[] args) cil managed
{
...
ldc.i4.5
stfld int32 LocalFunction_Example/'<>c__DisplayClass1_0'::x
...
call void LocalFunction_Example::'<MyFunc>g__DoIt1_0'(valuetype LocalFunction_Example/'<>c__DisplayClass1_0'&)
}
.method assembly hidebysig static void '<MyFunc>g__DoIt0_0'(valuetype LocalFunction_Example/'<>c__DisplayClass0_0'& '') cil managed
{
...
LocalFunction_Example/'<>c__DisplayClass0_0'::x
call void [mscorlib]System.Console::WriteLine(int32)
...
}
}
Note that DoIt
function has turned into a static function in the same class as its parent function.
Also the enclosed variable x
has turned into a field in a nested struct
(not nested class
as in the Anonymous Method example).
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