在 C# 中,if 语句或对不执行任何操作的函数的虚函数调用哪个更快?为什么?

What is faster in C#, an if statement, or a virtual function call to a function that does nothing? And why?

假设您有一个名为 MyClass 的 class,它使用对另一个名为 Behavior 的 class 的引用 (myBehavior) 封装了某种行为。默认情况下 MyClass 应该没有行为。

对于初始化后没有设置 myBehavior 的实例 - 如果将 myBehavior 初始化为 null 并且每次都是需要用 if(myBehavior) 检查,或者如果它被初始化为一个 NullBehavior 的实例会更快,派生自 Behavior,什么都不做?为什么?

class MyClass
{
   Behavior myBehavior = null;

   void doSomething()
   {
      if(myBehavior)
      {
         myBehavior.performAction();
      }
   }
}

或:

class NullBehavior : Behavior
{
   override void performAction()
   {
      // don't do anything
   }
}

class MyClass
{
   Behavior myBehavior = new NullBehavior(); // or equals some static universal instance of NullBehavior

   void doSomething()
   {
      myBehavior.performAction();
   }
}

让我们想象一下 ASM 代码(在 IL 之后)会发生什么:

  • if包装它会产生额外的mov + cmp + jnz指令。

  • 调用函数将执行影响调用堆栈维护(保存和恢复)的callret调用。它可能会生成如下内容:call ... 然后 push ebp mov ebp, esp ... pop ebp ret 保存它,然后额外的代码来恢复它。

显然调用函数比 if 消耗更多 CPU 操作。但另一方面,如果每次都会调用您的调用函数(即通常设置 myBehavior),那么我们将在 jnz/if.

上浪费额外的操作

因此,如果您可以预测 myBehaviour 最有可能被设置(不是 null / NullBehavior),那么您应该选择第二个选项而没有额外的 if 但如果它更有可能是 null 那么值得用 if.

包装它