C#里,派生类的方法里的匿名delegate调用基类的方法会产生无法验证的代码
2009-06-04 08:30:17 来源:WEB开发网核心提示: 错误所对应的IL代码为: Java代码IL_0011: call instance void Alpha::Blah()也就是原本的base.Blah(), 一个有趣的观察:虽然C#的语言规范中没有说明具体该如何为闭包生成代码,C#里,派生类的方法里的匿名delegate调用
错误所对应的IL代码为:
Java代码
IL_0011: call instance void Alpha::Blah()
也就是原本的base.Blah()。
一个有趣的观察:虽然C#的语言规范中没有说明具体该如何为闭包生成代码,但.NET Framework与Mono所做的几乎是一样的。这大概是因为Mono要尽量保持与.NET Framework的兼容吧。
前面的例子是用匿名delegate,在C# 3.0中换成Lambda Expression也一样:
C#代码
public void Charlie( ) { // int x = 123;
int x = 123;
D d = ( ) => {
this.Blah( );
base.Blah( );
Console.WriteLine( x );
};
d( );
}
上面提到了编译器会生成不可验证代码的状况。不过要是把前面例子中Charlie()里的x给去掉,变成这样的话:
C#代码
public void Charlie( ) {
D d = delegate {
this.Blah( );
base.Blah( );
};
d( );
}
那么.NET Framework的C#编译器能发现唯一的逃逸变量是this,于是不会生成一个私有的内部类,而是直接将那个匿名delegate生成为Bravo的一个私有成员方法。也就是生成类似这样的代码:
C#代码
public class Bravo : Alpha {
public override void Blah() {
Console.WriteLine("Bravo.Blah");
base.Blah();
}
// compiler generated method
public void __method() {
this.blah();
// on the next line, no such "__nonvirtual__" in C#
__nonvirtual__ ((Alpha)this).Blah());
}
public void Charlie() {
D d = new D(this.__method);
d();
}
}
换句话说,当逃逸变量只有this时,编译器并不会生成不可验证的变量。不过为了外表上行为的一致性,.NET Framework的C#编译器仍然会给出跟上面一样的警告。
Mono方面则是没有做这样的优化,仍然会与前面所说的状况一样,生成不可验证的代码。
- ››方法 (Array)
- ››方法和作用域中的内部类
- ››方法调用的绑定
- ››派生线程类
- ››匿名FTP服务器的建立与应用
更多精彩
赞助商链接