In. in. NET, a function is not a first-level member, so it cannot implement a closure by embedding a subfunction in a function like JavaScript. In general, there are some unnecessary conditions for closure formation:
· Nested defined functions.
· Anonymous functions.
· Use a function as a parameter or return value.
In. NET, the closure can be formed through anonymous delegation:
Delegate void MessageDelegate ();
Static void Main (string [] args)
{
String value = "Hello, Closure .";
MessageDelegate message = delegate ()
{
Show (value );
};
Message ();
}
Private static void Show (string message)
{
Console. WriteLine (message );
}
In fact, in most advanced languages that support closures, functions are the first-level members. functions can be passed as parameters, returned as return values, or function variables. while in.. NET. For more information about delegation, see section 9.7 "delegation, anonymous method, and Lambda expression ", therefore, the above logic can also implement simpler code through Lambda expressions.
The above example is the IL code:
. Class private auto ansi beforefieldinit Program
Extends [mscorlib] System. Object
{
. Method private hidebysig static void Main (string [] args) cel managed
{
// Omitted
}
. Class auto ansi sealed nested private beforefieldinit <> c _ DisplayClass1
Extends [mscorlib] System. Object
{
. Custom instance void [mscorlib] System. Runtime. CompilerServices. CompilerGenerated Attribute:. ctor ()
. Method public hidebysig specialname rtspecialname instance void. ctor () cel managed
{
// Omitted
}
. Method public hidebysig instance void <Main> B _ 0 () cel managed
{
// Omitted
}
. Field public string value
}
}
[NextPage]
A closure is automatically formed through the anonymous method. The free variable value is encapsulated in an internal class (closure) and upgraded to an instance Member. Even if the method for creating the variable is completed, this variable will not be released, but will be recycled by GC only after all callback functions are executed. the life cycle of the free variable value is extended and is not limited to a local variable. the delay in the life cycle is the benefit of the closure, but it also often brings about potential problems, resulting in more consumption.
1. Closures and functions
A function like an object is the biggest function of a closure, thus implementing a modular programming method. However, closure and function are not the same thing.
· A closure is an entity composed of a function and its referenced environment. Different referenced environments and the same function can be combined to generate different closure instances.
· A function is an executable code body that does not change in the Context during runtime.
2. Application Closure
Closures are functional programming genie. On the. NET platform, this genie also brings many applications. The typical performance is mainly reflected in the following aspects.
· Define the control structure to implement modular applications. closures implement the development of module applications with the smallest granularity in the simplest way, and achieve a certain degree of algorithm reuse. The ForEach in the next example provides the basis for reusing array elements, for addition and subtraction operations, change the value of referenced environment variables in the closure to achieve the minimum granularity of the module control effect.
Static void Main ()
{
Int [] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Int result1 = 0;
Int result2 = 100;
Values. ForEach (x => result1 + = x );
Values. ForEach (x => result2-= x );
Console. WriteLine (result1 );
Console. WriteLine (result2 );
}
· Multiple Functions share the same context environment to achieve data exchange through context variables.
Static void Main ()
{
Int value = 100;
IList <Func <int> funcs = new List <Func <int> ();
Funcs. Add () => value + 1 );
Funcs. Add () => value-2 );
Foreach (var f in funcs)
{
Value = f ();
Console. WriteLine (value );
}
}
Data sharing facilitates the transmission of data between operations of different functions. However, this double-edged sword sometimes causes problems when data sharing is not required. In the preceding example, the value variable will share data between () => value + 1 and () => value-2 in different operations. if you do not want to transmit data between two operations, pay special attention to the introduction of intermediate volume coordination:
Static void Main ()
{
Int value = 100;
IList <Func <int> funcs = new List <Func <int> ();
Funcs. Add () => value + 1 );
Funcs. Add () => value-2 );
Foreach (var f in funcs)
{
Int v = f ();
Console. WriteLine (v );
}
}