在 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
指令。
调用函数将执行影响调用堆栈维护(保存和恢复)的call
和ret
调用。它可能会生成如下内容:call ...
然后 push ebp
mov ebp, esp
... pop ebp
ret
保存它,然后额外的代码来恢复它。
显然调用函数比 if
消耗更多 CPU 操作。但另一方面,如果每次都会调用您的调用函数(即通常设置 myBehavior
),那么我们将在 jnz
/if
.
上浪费额外的操作
因此,如果您可以预测 myBehaviour
最有可能被设置(不是 null / NullBehavior),那么您应该选择第二个选项而没有额外的 if
但如果它更有可能是 null
那么值得用 if
.
包装它
假设您有一个名为 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
指令。调用函数将执行影响调用堆栈维护(保存和恢复)的
call
和ret
调用。它可能会生成如下内容:call ...
然后push ebp
mov ebp, esp
... pop ebp
ret
保存它,然后额外的代码来恢复它。
显然调用函数比 if
消耗更多 CPU 操作。但另一方面,如果每次都会调用您的调用函数(即通常设置 myBehavior
),那么我们将在 jnz
/if
.
因此,如果您可以预测 myBehaviour
最有可能被设置(不是 null / NullBehavior),那么您应该选择第二个选项而没有额外的 if
但如果它更有可能是 null
那么值得用 if
.