Turn http://www.cnblogs.com/lazycoding/archive/2013/01/06/2847587.html
Behind the secret-msil
With the famous LINQPad, we can look at the MSIL code in more depth without any secrets. is a linqpad to use
We will look at three examples, the first lambda expression is as follows:
action<string> Dosomethinglambda = (s) + ={ Console.WriteLine (s); + local};
The corresponding normal function is this
action<string> Dosomethinglambda = (s) + ={ Console.WriteLine (s); + local};
The resulting MSIL code snippet is as follows:
dosomethingnormal:il_0000: nop il_0001: ldarg. 1 il_0002: call System.Console.WriteLineIL_0007: nop il_0008: ret <main >b__0:il_0000: nop il_0001: ldarg. 0
The biggest difference is that the method has a different name usage. Rather than declarations. In fact. The declaration is exactly the same. The compiler creates a new method within the class to implement this method. It's nothing new, just for us to use lambda expressions to make it easy to write code. From the MSIL code, we did the same thing. A method is called in the current object.
We'll show you the changes made by the compiler. In this legend. We can see that the compiler moved the lambda expression into a fixed method.
The second example shows the real magic of lambda expressions, in this case. We used both a normal method with global variables and a lambda expression with a captured variable. The code is as follows
voidMain () {int local =5; action<String> Dosomethinglambda = (s) = ={Console.WriteLine (s + local);}; global = local; Dosomethinglambda ("Test 1"); Dosomethingnormal ("Test 2"); int global; void Dosomethingnormal (string s) {Console.WriteLine (s + global);}
There's nothing different about it. The key is: How lambda expressions are handled by the compiler
Il_0000:newobj userquery+<>C__displayclass1. Ctoril_0005:stloc.1Il_0006:nop Il_0007:ldloc.1IL_0008:ldc.i4.5IL_0009:STFLD userquery+<>C__DisplayClass1.localIL_000E:ldloc.1IL_000F:LDFTN userquery+<>c__displayclass1.<main>B__0il_0015:newobj system.action<system.string>.. Ctoril_001a:stloc.0Il_001b:ldarg.0Il_001c:ldloc.1IL_001D:LDFLD userquery+<>C__DISPLAYCLASS1.LOCALIL_0022:STFLD UserQuery.GlobalIl_0027:ldloc.0Il_0028:ldstr"Test 1"Il_002d:callvirt system.action<system.string>. Invokeil_0032:nop Il_0033:ldarg.0Il_0034:ldstr"Test 2"Il_0039:call UserQuery.DoSomethingNormalIL_003E:nop DoSomethingNormal:IL_0000:nop Il_0001:ldarg.1Il_0002:ldarg.0 il_0003:ldfld userquery. Globalil_0008:box System.Int32IL_000D:call System.String.ConcatIL_0012:call System.Console.WriteLineIL_0017:nop Il_0018:ret <>c__DisplayClass1.<Main> b__0:il_0000:nop Il_0001:ldarg. 1 Il_0002:ldarg. 0 il_0003:ldfld userquery+<>c__ DisplayClass1.localIL_0008:box System.Int32IL_000D:call System.String.ConcatIL_0012:call System.Console.WriteLineIL_0017:nop il_0018:ret <>c__displayclass1. Ctor:IL_0000:ldarg. 0 Il_0001:call System.Object. Ctoril_0006:ret
As in the first example. The same mechanism. The compiler moves the lambda expression into a method. But the difference is that the compiler also generated a class this time. The method that the compiler generates for our lambda expression is placed in the class, which gives the captured variable a global scope, by doing so. A lambda expression can access a local variable. Because in MSIL. It is a global variable inside a class instance.
All variables can therefore be assigned/read in the object of the newly generated class. This resolves the reference problem between the variables. (In fact, only references to that class instance are preserved.) The compiler is also smart enough to put the captured variables inside the class. Therefore, there is not much performance problem when we use lambda. Anyway. Attention. A memory leak can be caused by maintaining a reference to the lambda expression. As long as the method is still there. The variable is still alive. Obvious. And now we know the reason.
Once again, we use illustrations to illustrate. In the case of this kind of closure. Not only will the method be moved. The captured variables will also be moved. All objects that have been moved are placed in a newly generated class. Therefore, a class without a name appears implicitly.
Lambda Master's Road Part III