如何使用callvirt调用base.ToString()导致StackOverflow异常?

wah*_*eed 5 .net c# cil

IL提供了两个用于调用函数的语句,即call和callvirt。调用用于调用非虚拟或静态函数或编译器不想对引用进行空检查的任何函数。

callvirt用于调用虚拟函数,非虚拟函数也被调用,因为编译器会在运行时对引用进行空检查。

现在,当通过C#通过CLR时,我发现了以下示例。

internal class SomeClass
{
   public override String ToString()
   {
      return base.ToString();
   }
}
Run Code Online (Sandbox Code Playgroud)

现在ToString()是虚拟函数,但是编译器可以正常生成调用指令,但是Jeffrey提到了为什么不生成callvirt的原因,因为在这种情况下ToString()将被递归调用并将导致StackOverFlow异常,我试图理解,但无法将这个想法包住心?谁能解释为什么会导致递归调用?

谢谢..

And*_*mer 3

据我所知,如果编译器生成 callvirt,就会发生 stackoverflow 异常,因为:

某些代码调用从类object继承的someclass类型的对象的 ToString 。*somclass" 方法的 ToString 调用其基类object的 ToString 方法。

如果此调用虚拟的,则不会导致从类对象调用 ToString ,而是调用实际类(即SomeClass)的 ToString 。

然后你就会陷入不定式循环,因为整个事情将从现在开始。

  • 我想知道如何将对 base.ToString() 的调用视为 SomeClass.ToString(),然后我想出了以下解释: 调用 base.ToString() 相当于 (Object(this)).ToString() ,但在运行时 (Object(this)) 的类型实际上是 SomeClass。因此,如果使用 callvirt(它确定实例的运行时类型并相应地调用),则在运行时调用的函数将是 SomeClass.ToString() ,它将调用自身,这将导致无限递归调用,从而导致 StackOverflow 异常。 (2认同)