Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C-sharp language specification.2004.pdf
Скачиваний:
14
Добавлен:
23.08.2013
Размер:
2.55 Mб
Скачать

C# LANGUAGE SPECIFICATION

1end example]

2Separate anonymous methods can capture the same instance of an outer variable. [Example: In the following

3code:

4using System;

5delegate void Setter(int value);

6delegate int Getter();

7class Test

8{

9

static void Main() {

10

int x = 0;

11

Setter s = delegate(int value) { x = value; };

12

Getter g = delegate { return x; };

13

s(5);

14

Console.WriteLine(g());

15

s(10);

16

Console.WriteLine(g());

17}

18}

19the two anonymous methods capture the same instance of the local variable x, and they can thus

20“communicate” through that variable. The output of the example is:

215

2210

23end example]

2414.5.14.4 Anonymous method evaluation

25The run-time evaluation of an anonymous-method-expression produces a delegate instance which references

26the anonymous method and the (possibly empty) set of captured outer variables that are active at the time of

27the evaluation. When a delegate resulting from an anonymous-method-expression is invoked, the body of the

28anonymous method is executed. The code in the body is executed using the set of captured outer variables

29referenced by the delegate.

30The invocation list of a delegate produced from an anonymous-method-expression contains a single entry.

31The exact target object and target method of the delegate are unspecified. In particular, it is unspecified

32whether the target object of the delegate is null, the this value of the enclosing function member, or some

33other object.

34Evaluation of sematically identical anonymous-method-expressions with the same (possibly empty) set of

35captured outer variable instances is permitted (but not required) to return the same delegate instance. The

36term “sematically identical” is used here to mean that execution of the anonymous methods will, in all cases,

37produce the same effects given the same arguments. [Example: This rule permits code such as the following

38to be optimized.

39delegate double Function(double x);

40class Test

41{

42

static double[] Apply(double[] vector, Function func) {

43

double[] result = new double[vector.Length];

44

foreach (int i = 0; i < vector.Length; i++) {

45

result[i] = func(vector[i]);

46

}

47

return result;

48

}

184

Chapter 14 Expressions

1

static void F(double[] vx, double[] vy) {

2

double[] rx = Apply(vx, delegate(double x) {

3

return Math.Sin(x);

4

});

5

double[] ry = Apply(vy, delegate(double y) {

6

return Math.Sin(y);

7

});

8

9}

10}

11Since the two anonymous method delegates have the same (empty) set of captured outer variables, and since

12the anonymous methods are semantically identical, the compiler is permitted to have the delegates refer to

13the same target method. Indeed, the compiler is permitted to return the very same delegate instance from

14both anonymous method expressions.

15end example]

1614.5.14.5 Implementation example

17[Note: This subclause describes a possible implementation of anonymous methods in terms of standard

18C# constructs. The implementation described here is by no means a mandated implementation, nor is it the

19only one possible.

20The remainder of this subclause gives several examples of code that contains anonymous methods with

21different characteristics. For each example, a corresponding translation to code that uses only standard C#

22constructs is provided. In the examples, the identifier D is assumed to represent the following delegate type:

23public delegate void D();

24The simplest form of an anonymous method is one that captures no outer variables:

25class Test

26{

27

static

void F() {

28

D d

= delegate { Console.WriteLine("test"); };

29}

30}

31This can be translated to a delegate instantiation that references a compiler-generated static method in which

32the code of the anonymous method is placed:

33class Test

34{

35

static

void F() {

36

D d = new D(__Method1);

37

}

 

38

static void __Method1() {

39

Console.WriteLine("test");

40}

41}

42In the following example, the anonymous method references instance members of this:

43class Test

44{

45

int x;

46

void F() {

47

D d = delegate { Console.WriteLine(x); };

48}

49}

50This can be translated to a compiler-generated instance method containing the code of the anonymous

51method:

52class Test

53{

54

int x;

185

 

C# LANGUAGE SPECIFICATION

1

void F() {

2

D d = new D(__Method1);

3

}

4

void __Method1() {

5

Console.WriteLine(x);

6}

7}

8In this example, the anonymous method captures a local variable:

9class Test

10{

11

void F() {

12

int y = 123;

13

D d = delegate { Console.WriteLine(y); };

14}

15}

16The lifetime of the local variable shall now be extended to at least the lifetime of the anonymous method

17delegate. This can be achieved by “lifting” the local variable into a field of a compiler-generated class.

18Instantiation of the local variable (§14.5.14.3.2) then corresponds to creating an instance of the compiler-

19generated class, and accessing the local variable corresponds to accessing a field in the instance of the

20compiler-generated class. Furthermore, the anonymous method becomes an instance method of the

21compiler-generated class:

22class Test

23{

24

void F() {

25

__Locals1 __locals1 = new __Locals1();

26

__locals1.y = 123;

27

D d = new D(__locals1.__Method1);

28

}

29

class __Locals1

30

{

31

public int y;

32

public void __Method1() {

33

Console.WriteLine(y);

34

}

35}

36}

37Finally, the following anonymous method captures this as well as two local variables with different

38lifetimes:

39class Test

40{

41

int x;

42

void F() {

43

int y = 123;

44

for (int i = 0; i < 10; i++) {

45

int z = i * 2;

46

D d = delegate { Console.WriteLine(x + y + z); };

47

}

48}

49}

50Here, a compiler-generated class is created for each statement block in which locals are captured such that

51the locals in the different blocks can have independent lifetimes. An instance of __Locals2, the compiler-

52generated class for the inner statement block, contains the local variable z and a field that references an

53instance of __Locals1. An instance of __Locals1, the compiler-generated class for the outer statement

54block, contains the local variable y and a field that references this of the enclosing function member. With

55these data structures it is possible to reach all captured outer variables through an instance of __Locals2,

56and the code of the anonymous method can thus be implemented as an instance method of that class.

186

Соседние файлы в предмете Электротехника