什么';这是';这';在C#中?

什么';这是';这';在C#中?,c#,clr,C#,Clr,在“通过C#的CLR”第170页: 理论上,上面的代码很好。当然,变量p是空的,但是当调用非虚拟 方法(GetFive),CLR只需要知道p的数据类型,即程序。如果 若未调用GetFive,则此参数的值将为null。自从争论以来 如果未在GetFive方法内使用,则不会引发NullReferenceException 原谅我的愚蠢。我记得CLR通过“this”定位真正的方法代码,它总是隐式地出现在方法delcare的第一个参数中,为什么它会说“调用非虚拟 方法(GetFive),CLR只需要

在“通过C#的CLR”第170页:


理论上,上面的代码很好。当然,变量p是空的,但是当调用非虚拟 方法(GetFive),CLR只需要知道p的数据类型,即程序。如果 若未调用GetFive,则此参数的值将为null。自从争论以来 如果未在GetFive方法内使用,则不会引发NullReferenceException


原谅我的愚蠢。我记得CLR通过“this”定位真正的方法代码,它总是隐式地出现在方法delcare的第一个参数中,为什么它会说“调用非虚拟
方法(GetFive),CLR只需要知道p'的数据类型?

CLR不会对非虚拟方法执行空检查。基本上,如果使用
call
指令调用方法,CLR不会检查该
指针是否为null。相反,
callvirt
指令总是检查空值。但是,无论方法是否为虚拟方法,C#都会发出
callvirt
指令


这篇文章的意思是,如果C编译器为非虚方法发出语义上更合适的
call
指令,而不是
callvirt
指令,那么所讨论的代码不会抛出
NullReferenceException
。我记得,编译器团队决定几乎总是发出
callvirt
指令,因为它能更好地处理版本控制(JIT还可以将
callvirt
优化为
调用


请参见

CLR不会对非虚拟方法执行空检查。基本上,如果使用
call
指令调用方法,CLR不会检查该
指针是否为null。相反,
callvirt
指令总是检查空值。但是,无论方法是否为虚拟方法,C#都会发出
callvirt
指令


这篇文章的意思是,如果C编译器为非虚方法发出语义上更合适的
call
指令,而不是
callvirt
指令,那么所讨论的代码不会抛出
NullReferenceException
。我记得,编译器团队决定几乎总是发出
callvirt
指令,因为它能更好地处理版本控制(JIT还可以将
callvirt
优化为
调用


请参见

引用其自身(类)的当前实例

你的代码片段

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

不工作,因为您试图调用
null
的方法
GetFive
,一个不存在的
Program
——换句话说,您试图敲开一扇空的门,一扇不存在的门。由于CLR不知道门的位置,它会为您抛出一个异常“找不到函数门!”——比未定义的行为要好得多。

引用自身的当前实例(类)

你的代码片段

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

不工作,因为您试图调用
null
的方法
GetFive
,一个不存在的
Program
——换句话说,您试图敲开一扇空的门,一扇不存在的门。由于CLR不知道门的位置,它会为您抛出一个异常“找不到功能门!”——比未定义的行为要好得多。

好的。我刚刚通过C#查阅了CLR第170页,第三版

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

c#始终默认为callvirt,因此没有问题,但是对于调用方,您无法提前知道这一点。如果您这样做,您可能会无意中破坏别人的程序,如果您正在运送库或API


试试这个

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

好的。我刚刚通过C#查阅了CLR第170页,第三版

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

c#始终默认为callvirt,因此没有问题,但是对于调用方,您无法提前知道这一点。如果您这样做,您可能会无意中破坏别人的程序,如果您正在运送库或API


试试这个

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

但是“GetFive”是一个实例方法,而不是静态方法。即使在“GetFive”方法中没有使用任何实例变量,运行时仍然需要知道该方法在哪个对象实例上执行。@Kirk Woll我认为该段落是书中的引用,但“GetFive”是一个实例方法,而不是静态的。即使您没有在“GetFive”方法中使用任何实例变量,运行时仍然需要知道该方法在哪个对象实例上执行。@Kirk Woll我认为该段落引用了书中的一段话。我认为OP意识到为什么会在c#中抛出nullreferenceexception,但他的问题是“为什么“CLR通过C#”中的这段话说CLR不会检查非虚拟方法的null”…编辑:但是,再看看问题的标题,我不太确定问题是什么…我想OP知道为什么在C#中抛出nullreferenceexception,但他的问题是”为什么“CLR通过C#”的这段话说CLR是d