[英]What's the meaning of 'this' in C#?
在“通过C#执行CLR”的第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的数据类型'?
CLR不会对非虚拟方法进行null检查。 基本上,如果使用call
指令call
方法,则CLR不会检查this
指针是否为null。 相反, callvirt
指令始终检查无效性。 但是,无论该方法是否为虚拟方法,C#都会发出callvirt
指令。
这段话说的是,如果C#编译器针对非虚拟方法发出了语义上更合适的call
指令,而不是callvirt
指令,那么所讨论的代码将不会抛出NullReferenceException
。 我记得,编译器团队决定几乎总是发出callvirt
指令,因为它更好地处理了版本控制(而且JIT可以将callvirt
优化为call
)。
this
是指自身(类)的当前实例。
您的代码段,
Program p = null;
Int32 x = p.GetFive(); // In C#, NullReferenceException is thrown
之所以不起作用,是因为您试图调用null
GetFive
方法(一个不存在的Program
实例)-换句话说,您试图敲开一个无效的门,一个不存在的门。 由于CLR不知道门的位置,因此抛出异常“找不到功能门!”。 对您来说-比不确定的行为要好得多。
好的。 我只是通过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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.