documentation与 is
运算符(expr is constant
)的常量模式匹配状态:
The constant expression is evaluated as follows:
If
expr
andconstant
are integral types, the C# equality operator determines whether the expression returnstrue
(that is, whetherexpr == constant
).Otherwise, the value of the expression is determined by a call to the static
Object.Equals(expr, constant)
method.
因此,在使用这段代码的时候
public bool IsZero(int value)
{
return value is 0;
}
我希望它使用 ==
运算符(案例 1)并生成此代码:
.method public hidebysig instance bool
IsZero(
int32 'value'
) cil managed
{
.maxstack 8
ldarg.1
ldc.i4.0
ceq
ret
}
然而,在reality ,整数参数和常量(文字)被装箱以便传递给静态 Object.Equals
方法(情况 2):
.method public hidebysig instance bool
IsZero(
int32 'value'
) cil managed
{
.maxstack 8
ldc.i4.0
box [mscorlib]System.Int32
ldarg.1
box [mscorlib]System.Int32
call bool [mscorlib]System.Object::Equals(object, object)
ret
}
为什么会这样?
最佳答案
编译器在所有情况下都是相同的 - Roslyn。虽然不同的版本产生不同的 IL。 C# 8 版本不装箱,而旧版本则装箱。
例如,2.9.0此代码段的 IL:
using System;
public class C {
public bool IsZero(int value)
{
return value is 0;
}
}
是
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: box [mscorlib]System.Int32
IL_0007: ldarg.1
IL_0008: box [mscorlib]System.Int32
IL_000d: call bool [mscorlib]System.Object::Equals(object, object)
IL_0012: stloc.0
IL_0013: br.s IL_0015
IL_0015: ldloc.0
IL_0016: ret
使用任何 C# 8 versions虽然在 Debug模式下产生这个:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldc.i4.0
IL_0003: ceq
IL_0005: stloc.0
IL_0006: br.s IL_0008
IL_0008: ldloc.0
IL_0009: ret
这在 Release 中.
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: ceq
IL_0004: ret
这与问题中的预期代码相同
关于c# - 为什么 is-operator 会导致不必要的装箱?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56561692/