C#中'this'的含义是什么?

时间:2011-08-03 05:07:04

标签: c# clr

在'CLR via C#'的第170页:


public sealed class Program {
    public Int32 GetFive() { return 5; }
    public static void Main() {
       Program p = null;
       Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown
    }
}

理论上,上面的代码很好。当然,变量p为null,但在调用非虚拟时 方法(GetFive),CLR只需要知道p的数据类型,即Program。如果 GetFive确实被调用了,这个参数的值将为null。自从争论 在GetFive方法中没有使用,不会抛出NullReferenceException。


请原谅我的傻瓜。我记得CLR通过'this'找到真正的方法代码,它始终隐含地用于方法delcare中的第一个参数,为什么它说'在调用非虚拟时 方法(GetFive),CLR只需知道p'的数据类型

3 个答案:

答案 0 :(得分:5)

CLR不会对非虚方法进行空检查。基本上,如果使用call指令调用方法,则CLR不会检查空this指针。相反,callvirt指令始终检查无效。但是,无论方法是否为虚拟,C#都会发出callvirt指令。

该段落的内容是,如果C#编译器为非虚方法发出了语义上更合适的call指令而不是callvirt指令,那么有问题的代码就不会抛出{{ 1}}。我记得,编译器团队决定几乎总是发出NullReferenceException指令,因为它更好地处理版本控制(JIT也可以将callvirt优化为callvirt)。

请参阅http://www.pvle.be/tag/clr/

答案 1 :(得分:3)

this指的是它自身的当前实例(该类)。

您的代码段,

Program p = null;
Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown

无效,因为您正在尝试调用GetFive null的方法Program,这是一个不存在的{{1}}实例 - 换句话说,您正试图敲门一个虚空,一扇不存在的门。由于CLR不知道门的位置,因此抛出异常“无法找到功能门!”对你而言 - 比未定义的行为要好得多。

答案 2 :(得分:0)

好。我只是通过C#,第3版查阅了CLR第170页。

也许页面的重点是 重要 部分,其中另一个CLR语言编译器生成一些使用您的C#类的代码,然后您将C#代码更改为一个非虚方法,不重新编译引用C#库的代码。在这种情况下,可能会出现问题,具体取决于调用者是实现call还是callvirt(未定义编译器将执行的操作)。

c#总是默认为callvirt,所以没问题,但对于来电者你不能提前知道。如果你这样做,如果你要运送图书馆或API,你可能会无意中破坏别人的程序。


试试这个。

    public static Int32 GetFive() { return 5; }    
    public static void Main() {       
        Int32 x = GetFive(); 
    }