It turns out that: How does the closure in C # capture variables?

Source: Internet
Author: User

We know that in an anonymous method or lambda, you can access or modify the variables within the defined range of the token. For example:
Int num = 1;
Func <int> incNum = () => ++ num;
Lambda expressions use the variable num defined externally. We can think that the lambda statement block in this section constitutes a closure, which captures the external variable num.
Well, let alone so many uncomfortable definitions. Let's start with the question and see how variables are captured in C. Let's look at an example:
Public Func <String> CreateFunction ()
{
String str = "My lucky number is ";
Int num = 17;
Func <String> func = () => str + num;
Return func;
}
In this example, a CreateFunction method is defined to return a function. The returned function forms a closure that captures two variables: str of the String type and num of the int type.
Now we can use this function as follows:
Func <String> myFunc = CreateFunction ();
String result = myFunc ();
Let's analyze what the two lines of code actually do. The first line is easy to understand. We assigned the anonymous function generated by CreateFunction to the delegate myFunc. The second line is better understood. We executed myFunc and assigned the returned result to the result variable. Let's take a deeper look: When executing myFunc, two variables str and num are defined in CreateFunction. Although the stack frame of CreateFunction has been destroyed for a long time, the variables defined in CreateFunction are still "unknown", but we know that these two variables have been captured by the closure, so we firmly believe that these two variables can still be accessed so far!
For a str object, given that it is a reference type, it will not be destroyed as long as there is a "thing" that stores references to it. In this way, we do not have to worry that the compiler or runtime will tell us that it is lost when we need it. However, for num, the situation is somewhat different. Num is a value type. We know that the value type is alive on the stack. We also know that the stack frame (I .e. the CreateFunction frame) exists in it will be destroyed after CreateFunction is executed, then any value types on it will be destroyed together, which includes the variable num that we are concerned.
So why can we securely access num? What is the magic of the variable capture mechanism in C # that allows the value type to have a life cycle that violates the conventional rules? Packing! You may immediately think that by adding each value type to an object, we can make this value type have the same lifetime as the object wrapped in it. However, this is not the method selected by the C # implementer! C # Does not pack each value type variable to be captured, instead, all the captured variables are put in the same big "box"-when the compiler encounters a situation where variable capture is required, it will silently construct a type in the background, this type contains the variables captured by each closure (including value type variables and reference type variables) as one of its public fields. In this way, the compiler can
It is easy and pleasant to maintain external variables that appear in anonymous functions or lambda expressions. Furthermore, if we use the ILDASM tool to view the IL code of the CreateFunction method, we will find that the compiler does not declare the num and str variables at all. Instead, a type name and Instance name are declared and their ugly packaging objects are declared. This is the one we mentioned above, which is silently generated by the compiler and stores all referenced objects that capture variables. We can also see that all the operations on str and num in the CreateFunction method C # source code are converted into the operation of the public member with the same name as the packaging object in IL. By the way, even the lambda expression "() => str + num" We constructed is now converted into a method for packaging this object by the compiler!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.