日期:2013-02-08  浏览次数:20444 次

第三章 匿名方法
原著:Microsoft Corporation
原文:http://msdn.microsoft.com/vcsharp/team/language/default.aspx (SpecificationVer2.doc)
翻译:lover_P
出处:


--------------------------------------------------------------------------------

[内容]

3.1 匿名方法表达式
3.2 匿名方法签名
3.3 匿名方法转换
3.3.1 委托建立表达式
3.4 匿名方法块
3.5 外部变量
3.5.1 捕获外部变量
3.5.2 局部变量的实例化
3.6 匿名方法求值
3.7 委托实例相等性
3.8 明确赋值
3.9 方法组转换
3.10 实现实例


3.1 匿名方法表达式
匿名方法表达(anonymous-method-expression)式定义了匿名方法(anonymous method),并求得一个引用了该方法的特殊的值。

primary-no-array-creation-expression:

anonymous-method-expression
anonymous-method-expression:
delegate anonymous-method-signatureopt block

anonymous-method-signature:
( anonymous-method-parameter-listopt )

anonymous-method-parameter-list:
anonymous-method-parameter
anonymous-method-parameter-list , anonymous-method-parameter

anonymous-method-parameter:
parameter-modifieropt type identifier

初等非数组表达式:
...
匿名方法表达式

匿名方法表达式:
delegate 匿名方法签名可选 块

匿名方法签名:
( 匿名方法参数列表可选 )

匿名方法参数列表:
匿名方法参数
匿名方法参数 , 匿名方法参数

匿名方法参数:
参数修饰符可选 类型 标识符


匿名方法表达(anonymous-method-expression)是一个遵从特殊转换规则(见3.3)的值。这个值没有类型,但可以隐式地转换为一个兼容的委托类型。

匿名方法表达式(anonymous-method-expression)为参数、局部变量和常量以及标签定义了一个新的声明空间。

3.2 匿名方法签名
可选的匿名方法签名(anonymous-method-signature)为匿名方法的形式参数定义了名字和类型。这些参数的作用于是匿名方法的块(block)。如果一个局部变量的作用域包含了匿名方法表达式(anonymous-method-expression),且该匿名方法的参数和该局部变量相同,则会产生编译错误。

如果一个匿名方法表达式(anonymous-method-expression)具有匿名方法签名(anonymous-method-signature),则与之兼容的委托类型被强制具有相同的参数类型和修饰符,且具有相同顺序(见3.3)。如果一个匿名方法表达式(anonymous-method-expression)没有匿名方法签名(anonymous-method-signature),则与之相兼容的委托类型被强制要求没有out参数。

注意匿名方法签名(anonymous-method-signature)不能包含特性或参数数组(译注:用于实现变长参数列表)。然而,一个匿名方法签名(anonymous-method-signature)可以和一个包含参数数组的委托类型相兼容。

3.3 匿名方法转换
匿名方法表达式(anonymous-method-expression)是一个没有类型的特殊值。一个匿名方法表达式(anonymous-method-expression)可以用于委托建立表达式(delegate-creation-expression)(见3.3.1)。对于匿名方法表达式(anonymous-method-expression)的其他有效的应用取决于定义于其上的隐式转换。

匿名方法表达式(anonymous-method-expressio)与任何兼容的委托类型之间均存在隐式转换。如果D是一个委托类型,而A是一个匿名方法表达式(anonymous-method-expression),当且仅当以下两个条件成立的时候D和A是兼容的。

首先,D的参数类型必须与A兼容:
如果A不含匿名方法签名(anonymous-method-signature),则D可以具有任意类型的零或多个参数,但这些参数不能带有out修饰符。

如果具有匿名方法签名(anonymous-method-signature),则D必须具有和A形同数量的参数,A中的每个参数必须和D中相应的参数具有相同的类型,并且A中每个参数上的ref或out修饰符的出现与否必须与D中的相应参数相同。如果D中的最后一个参数是参数数组,则没有相互兼容的A和D。

其次,D的返回值类型必须与A兼容。由于这一规则,A中不能包含其他匿名方法的块(block)。
如果D的返回值类型被声明为void,则A中包含的所有return语句不能指定表达式。

如果D的返回值类型被声明为R,则A中包含的所有return语句不许指定一个能够隐式转换为R的表达式。A中的块(block)的终点必须可达。

除了和相兼容的委托类型之间的隐式转换,匿名方法表达式(anonymous-method-expression)与任何类型之间不存在任何转换,包括object类型。

下面的例子详细地解释了这些规则:

delegate void D(int x);

D d1 = delegate { }; // 正确
D d2 = delegate() { }; // 错误,签名不匹配
D d3 = delegate(long x) { }; // 错误,签名不匹配
D d4 = delegate(int x) { }; // 正确
D d5 = delegate(int x) { return; }; // 正确
D d6 = delegate(int x) { return x; }; // 错误,返回值不匹配

delegate void E(out int x);

E e1 = delegate { }; // 错误,E带有一个输出参数
E e2 = delegate(out int x) { x = 1; }; // 正确
E e3 = delegate(ref int x) { x = 1; }; // 错误,签名不匹配

delegate int P(params int[] a);

P p1 = delegate { }; // 错误,块的结尾不可达
P p2 = delegate { return; }; // 错误,返回值类型不匹配
P p3 = delegate { return 1; }; // 正确
P p4 = delegate { return "Hello"; }; // 错误,返回值类型不匹配

P p5 = delegate(int[] a) { // 正确
return a[0];
};

P p6 = d