21.7 Entrusted instances equal
The following rules apply to the results of the equality operator (§7.9.8) and Object.Equals methods to be entrusted by an anonymous method.
l When the entrustment example is calculated by the same anonymous method expression as the semantic method of the set of external variables, it can be said (but not necessarily) they are equal.
l When the delegate example is expressed by an anonymous method with semantics, or when there is a collection of different captured external variables, they are not equal.
21.8 Clear assignment
The explicit assignment status of an anonymous method parameters is the same as named methods. That is, the reference parameters and value parameters are explicitly assigned, and the output parameters do not need to be assigned. Also, the output parameter must be explicitly assigned before the anonymous method is returned (§ 5.1.6).
When controlling the block of the anonymous method expression, the explicit assignment state of the external variable V is the same as the explicit assignment status of V before the anonymous method expression. That is, the explicit assignment of external variables will be inherited from anonymous method expression context. In an anonymous method block, it is clearly assigned to be interpreted as if it is in a normal block (§ 5.3.3).
The explicit assignment status of the variable V after an anonymous method expression is the same as that of its explicit assignment status before an anonymous method expression.
E.g
Delegate Bool Filter (INT I);
Void f () {int max;
// Error, MAX does not make a clear assignment filter f = delegate (int N) {return n MAX = 5; DOWORK (f);} A compile error will be generated because Max is not explicitly assigned in the place where the anonymity method is declared. Example Delegate void d (); Void f () {int N; D = delegate {n = 1; d (); // Error, N does not make a clear assignment console.writeLine (N);} A compile error will also be generated because the value of N inside the anonymous method does not have an effect on the explicit assignment status of the anonymous method. 21.9 Method Group Conversion Similar to the implicit anonymous method described in §21.3, there is also an implicit conversion from the method group (§ 7.1) to the compatible delegate type. For a given method group E and the delegate type D, if the entrustment of the New D (E) is allowed to create an expression (§7.5.3 and §20.9.6), then there is an implicit conversion from E to D, and The result of the conversion is exactly equivalent to NEW D (E). In the following example Using system; using system.windows.forms; Class alertdialog {label message = new label (); button okbutton = new button (); button canbutton = new button (); ` Public alertdialog () {okbutton.click = new eventhandler (okclick); cancelButton.Click = new eventhandler (CancelClick); ...} Void Okclick (Object Sender, Eventargs E) {...} Void CancelClick (Object Sender, Eventargs E) {...}} The constructor creates two delegate instances with NEW. Implicit method group conversion allows simplification Public alertdialog () {okbutton.click = okclick; cancelButton.Click = CancelClick; ...} For all other implicit and explicit conversions, the conversion operator can be used to explicitly perform a specific conversion. To do this, an example object obj = new eventhandler (MyDialog.okClick); It can be used instead of writing as follows. Object obj = (eventhandler) mydialog.okclick; Method combination anonymous methods expressions can affect overload resolution, but they do not participate in type inference. See §20.6.4 Get more detailed information. 21.10 Implementation Example This section describes the possible implementation of anonymous methods in the form of a standard C # component. The implementation described herein is based on the same principle used by the Microsoft C # compiler, but it is not necessarily mandatory or the only possible implementation of ã. The rear portion of this section gives several example Ä code, which contains an anonymous methods with different characteristics. For each example, we will provide a corresponding conversion of code using the unique standard C # component. In these examples, the identifier D is assumed to represent the following delegate type. public Del Egate void d (); The simplest form of anonymous method is that there is no capture of the external variable. Class test {static void f () {â d d = Del Egate {console.writeline ("test");}; This code can be converted to a delegation example of a static method generated by a reference compiler, and the code of anonymity will be placed in the static method. , Class test {static void f () {d = new d (__Method1); Static void __method1 () {console.writeLine ("test");}} In the example below, an anonymous method references the instance members of this. Class test {int x; Void f () {d d = delegate {console.writeLine (x);}; This can be converted to an instance method that contains an anonymous method code generated by the compiler. Class test {int x; Void f () {d = new d (__ method1);} Void __method1 () {console.writeLine (x);}} In this example, anonymous method captures a ± part variable. Class test {void f () {int y = 123; D D = delegate {console.writeLine (y);}; The local variable's survival is now at least to extend to the survival of the anonymous method. This can be done by using the local variable "lifting" as the "Compiler-Generated) class generated by the compiler. Instantiation of local variables corresponds to an instance of the class generated by a compiler, and accessing a local variable will correspond to a field of the class instance generated by the compiler. Also, anonymous methods will become an instance method of the compiler generation class. Class test {void f () {__locals1 = new __locals1 (); __locals1.y = 123; d = new d (__ locals1 .__ method1);} Class __locals1 {public int y; Public void __method1 () {console.writeLine (Y);}}} Finally, the following anonymous methods will capture this, and two partial variables with different survival periods. Class test {int x; void f () {int y = 123; for (int i = 0; i <10; i ) {int Z = i * 2; D D = delegate {console.writeLine (x y z); }; } }} Here, the compiler will generate classes for each statement block, where local variables will be captured, while local variables in different blocks will have an independent survival period. __Locals2 instance, the compiler is the class generated by the internal statement block, contains the fields of local variable z and reference __locals1 instances. __Locals1 instance, the compiler is the class generated by the external statement block, contains the fields of the local variable Y and the TIS of the closure function member. Through these data structures, you can reach all captured local variables through an instance of __locals2, and the code for anonymous methods can be implemented as an instance method of that class. Class test {void f () {__locals1 = new __locals1 (); __locals1 (); __locals1 .__ this = this; __locals1.y = 123; for (int i = 0; i <10; i ) {__locals2 = new __locals2 (); __locals2. __locals1 = __locals1; __locals2.z = i * 2; D D = New D (__ locals2 .__ method1);}} Class __locals1 {public Test __this; public int y;} Class __locals2 {public __locals1 __locals1; public int z; Public void __method1 () {console.writeLine (__ locals1 .__ this.x __locals1.y z);}}} (The anonymous method is finished)