WEB开发网
开发学院软件开发C语言 C#里,派生类的方法里的匿名delegate调用基类的方... 阅读

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方面则是没有做这样的优化,仍然会与前面所说的状况一样,生成不可验证的代码。

上一页  1 2 3 4 5 6 

Tags:派生 方法 匿名

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接