- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在这种情况下,IL 并不总是对 virtual
方法使用 callvirt
指令:
class MakeMeASandwich{
public override string ToString(){
return base.ToString();
}
}
在这种情况下,据说 IL 将产生 call
而不是 callvirt
其中产生 callvirt
是为了检查 variable
是否为 null
,否则抛出 NullReferenceException
。
callvirt
而不是 call
,为什么递归调用会发生直到堆栈溢出?call
,那么它什么时候检查它用来调用方法的实例变量是否为空? 最佳答案
Why does a recursive invocation happen till stack overflow if callvirt is used instead of call?
因为这样你的代码就完全一样了:
override string ToString()
{
return this.ToString();
}
这显然是无限递归,前提是给定的方法是 ToString 的最重要版本。
If call is used, then how come it checks whether the instance variable it uses to call the methods is null or not?
这个问题是不可回答的,因为这个问题假定了一个谎言。调用指令不检查接收者的引用是否为空,所以问为什么调用指令检查空值没有任何意义。
让我为您改写成一些更好的问题:
Under what circumstances does the C# compiler generate a call vs a callvirt?
如果 C# 代码对虚方法 执行非虚调用,则编译器必须生成调用,而不是 callvirt。唯一一次真正发生这种情况是在使用 base
调用虚拟方法时。
如果 C# 代码正在执行一个虚拟调用,那么编译器必须生成一个 callvirt。
如果 C# 代码正在非虚拟方法 上执行非虚拟调用,则编译器可以选择生成 call 或 callvirt。两者都会起作用。 C# 编译器通常选择生成 callvirt。
The call instruction does not automatically do a null check, but callvirt does. If the C# compiler chooses to generate a call instead of a callvirt, is it also obligated to generate a null check?
没有。如果已知接收者不为空,则 C# 编译器可以跳过空检查。例如,如果您为非虚方法 M 说 (new C()).M()
,那么编译器生成 call
指令是合法的没有空检查。我们知道 (1) 该方法不是虚拟的,因此它不必是 callvirt
;我们可以选择是否使用callvirt
。我们知道 (2) new C()
永远不会为空,因此我们不必生成空检查。
如果 C# 编译器不知道接收者不为空,那么它将生成一个 callvirt,或者生成一个空检查然后调用。
关于c# - 为什么 callvirt IL 指令会导致虚方法中的递归调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10213413/
我有一个特别的问题想要解决,我不确定是否可行,因为我找不到任何信息或正在完成的示例。基本上,我有: class ParentObject {}; class DerivedObject : publi
在我们的项目中,我们配置了虚 URL,以便用户可以在地址栏中输入虚 URL,这会将他们重定向到原始 URL。 例如: 如果用户输入'http://www.abc.com/partner ',它会将它们
我是一名优秀的程序员,十分优秀!