Building a built-in lambda function in C #

If I have such a method

void SomeMethod () { Func<A,B> f = a => /*Some code*/; ... b = f (a); } 

is there an f created every time SomeMethod is SomeMethod ? I mean, does this line take time to compute or does the compiler store the function somewhere at compile time, skip it at runtime?

+6
source share
2 answers

Consider this simple example:

 static void Main(string[] args) { Test(); Test(); } static void Test() { Func<int, int> f = a => a * a; int b = f(2); Console.WriteLine(b); } 

Created Method:

enter image description here

And the IL code for <Test>b__0 :

 .method private hidebysig static int32 '<Test>b__0'(int32 a) cil managed { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Code size 8 (0x8) .maxstack 2 .locals init ([0] int32 CS$1$0000) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: mul IL_0003: stloc.0 IL_0004: br.s IL_0006 IL_0006: ldloc.0 IL_0007: ret } // end of method Program::'<Test>b__0' 

IL code for the Test method:

  .method private hidebysig static void Test() cil managed { // Code size 49 (0x31) .maxstack 2 .locals init ([0] class [mscorlib]System.Func`2<int32,int32> f, [1] int32 b) IL_0000: nop IL_0001: ldsfld class [mscorlib]System.Func`2<int32,int32> ConsoleApplication10.Program::'CS$<>9__CachedAnonymousMethodDelegate1' IL_0006: brtrue.s IL_001b IL_0008: ldnull IL_0009: ldftn int32 ConsoleApplication10.Program::'<Test>b__0'(int32) IL_000f: newobj instance void class [mscorlib]System.Func`2<int32,int32>::.ctor(object, native int) IL_0014: stsfld class [mscorlib]System.Func`2<int32,int32> ConsoleApplication10.Program::'CS$<>9__CachedAnonymousMethodDelegate1' IL_0019: br.s IL_001b IL_001b: ldsfld class [mscorlib]System.Func`2<int32,int32> ConsoleApplication10.Program::'CS$<>9__CachedAnonymousMethodDelegate1' IL_0020: stloc.0 IL_0021: ldloc.0 IL_0022: ldc.i4.2 IL_0023: callvirt instance !1 class [mscorlib]System.Func`2<int32,int32>::Invoke(!0) IL_0028: stloc.1 IL_0029: ldloc.1 IL_002a: call void [mscorlib]System.Console::WriteLine(int32) IL_002f: nop IL_0030: ret } // end of method Program::Test 

Each time you call the Test method, the cached anonymous delegate (which is Func<int,int> ) is loaded, then the Invoke method is called.

So the answer is: the anonymous method ( <Test>b__0 ) is created only once by the compiler, it is not created every time you call the function.

+4
source

The C # compiler creates a regular (non-anonymous) method from the lambda arrow, then the delegate f will have this "generated" method in its call list.

Each time SomeMethod is SomeMethod , a new instance of the Func<,> delegate is created, which refers to a regular (but generated) method.

What is it like:

 void SomeMethod () { Func<A, B> f = StrangeName; ... b = f(a); } static B StrangeName(A a) { /*Some code*/ } 
+3
source

Source: https://habr.com/ru/post/972267/


All Articles