There is the following C # code ( .NET Core ):

using System; public class LambdaTest { public static void Main() { MyClass obj = new MyClass(32); UnsafeFunc(obj); obj.EventCall(); Console.WriteLine(); obj.EventCall(); } public static void UnsafeFunc(MyClass obj) { int local = 10; obj.MyEvent += delegate { Console.WriteLine("Unsafe event"); local++; Console.WriteLine("Variable from function: {0}", local); }; } } public class MyClassArgs: EventArgs { public int Prop { get; set; } public MyClassArgs(int arg) { Prop = arg; } } public class MyClass { public int ObjProp { get; set; } public event EventHandler < MyClassArgs > MyEvent; public MyClass(int arg) { ObjProp = arg; } public void EventCall() { Console.WriteLine("Event call"); MyEvent(this, new MyClassArgs(64)); } } 

The UnsafeFunc(MyClass obj) method assigns the obj.MyEvent event obj.MyEvent anonymous method that changes and displays the local variable local , declared in UnsafeFunc(MyClass obj) . The first time the event is called, the local value is output: 11. The second time the call is: 12. But the fact is that local is a local variable of the method, i.e. after executing the method, the memory allocated to it seems to be cleaned up. Then how to explain that an event handler has access to memory, which should not exist?

1 answer 1

In programming languages, including C #, there is such a thing as closure. Its meaning is that if an anonymous method (say Inner) is declared in any method (let's call it Outer), using local variables of the Outer method, then references to these variables will be alive until Inner completes its work, even if the outer is already complete.

In your case, the UnsafeFunc method UnsafeFunc already worked, but the local variable is used in the obj.MyEvent event obj.MyEvent , and therefore the reference to it is saved by the garbage collector even after exiting the UnsafeFunc method.

In fact, in this case, the compiler creates an anonymous class, in the fields of which the captured variables are written, and in anonymous methods that capture these variables, it passes the fields of this class.