C# 方法时,实际递归调用自身

C# 方法时,实际递归调用自身,c#,clr,C#,Clr,我一直在通过C#阅读CLR,我读了以下内容: 有时,编译器将使用call指令来调用虚拟方法,而不是使用callvirt指令。起初,这似乎令人惊讶,但下面的代码说明了为什么有时需要它: internal class SomeClass { // ToString is a virtual method defined in the base class: Object. public override String ToString() { // Compiler uses the ‘call’

我一直在通过C#阅读CLR,我读了以下内容:

有时,编译器将使用call指令来调用虚拟方法,而不是使用callvirt指令。起初,这似乎令人惊讶,但下面的代码说明了为什么有时需要它:

internal class SomeClass {
// ToString is a virtual method defined in the base class: Object.
public override String ToString() {
// Compiler uses the ‘call’ IL instruction to call
// Object’s ToString method nonvirtually.
// If the compiler were to use ‘callvirt’ instead of ‘call’, this
// method would call itself recursively until the stack overflowed.
return base.ToString();
}
}
调用base.ToString(虚拟方法)时,C#编译器会发出一条调用指令,以确保以非虚拟方式调用基类型中的ToString方法。这是必需的,因为如果ToString被虚拟调用,调用将递归执行,直到线程的堆栈溢出,这显然是不需要的

虽然这里已经解释过了,但我不明白为什么被虚拟调用的ToString会递归执行。如果可能的话,有人能提供另一种解释或以更简单的方式描述它吗

谢谢

使用
base.ToString()
您实际上想要调用ToString()方法的基类实现

如果您只是调用
,那么将“虚拟地”调用此.ToString()
方法,即调用实际类的
ToString()


在您的示例中,如果
base.ToString()
将被“虚拟”调用,它将与
this.ToString()
相同,这将以
ToString()
方法结束,再次调用相同的
ToString()
因此将是一个以堆栈溢出结束的无限递归。

他还可以尝试
公共重写字符串ToString(){object thisaObject=this;返回thisaObject.ToString();}
类内部。在发布版本(启用优化)中,它通常不会以堆栈溢出结束(不在.NET 4.6 64位中)。JIT编译器可以将调用优化为尾部调用,因此它不会在堆栈上创建新的帧。关闭优化后,将出现堆栈溢出。