[英]Why does the is-operator cause unnecessary boxing?
The documentation of constant pattern matching with the is
-operator ( expr is constant
) states: 与is
-operator( 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
). 如果expr
和constant
是整数类型,则C#相等运算符确定表达式是否返回true
(即,expr == constant
)。Otherwise, the value of the expression is determined by a call to the static
Object.Equals(expr, constant)
method. 否则,表达式的值由对静态Object.Equals(expr, constant)
方法的调用确定。
Therefore, when using this code 因此,在使用此代码时
public bool IsZero(int value)
{
return value is 0;
}
I expect it to use the ==
operator (case 1) and generate this code: 我希望它使用==
运算符(情况1)并生成此代码:
.method public hidebysig instance bool
IsZero(
int32 'value'
) cil managed
{
.maxstack 8
ldarg.1
ldc.i4.0
ceq
ret
}
However, in reality , the integer parameter and the constant (literal) are boxed in order to be passed to the static Object.Equals
method (case 2): 但是, 实际上 ,整数参数和常量(文字)被加框,以便传递给静态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
}
Why is that the case? 为什么会这样?
The compiler is the same in all cases - Roslyn. 在所有情况下编译器都是相同的 - Roslyn。 Different versions produce different IL though. 不同的版本产生不同的IL。 The C# 8 versions don't box, while older ones do. C#8版本没有盒子,而旧版本没有盒子。
For example, with 2.9.0 the IL for this snippet : 例如,使用2.9.0此代码段的IL:
using System;
public class C {
public bool IsZero(int value)
{
return value is 0;
}
}
is 是
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
Using any of the C# 8 versions though produces this in debug mode : 使用任何C#8版本虽然在调试模式下生成:
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
IL_0000: ldarg.1
IL_0001: ldc.i4.0
IL_0002: ceq
IL_0004: ret
That's the same as the expected code in the question 这与问题中的预期代码相同
is operator Documentation states: 是运营商文档说明:
When performing pattern matching with the constant pattern,
is
tests whether an expression equals a specified constant. 当执行模式与恒定模式匹配,is
测试一个表达式是否等于指定常数。 InC# 6
and earlier versions, the constant pattern is supported by theswitch
statement. 在C# 6
及更早 版本中,switch
语句支持常量模式。 Starting withC# 7.0
, it's supported by theis
statement as well. 从C# 7.0
,它也受到is
语句的支持。
By default VS2017 using older version C#
compiler. 默认情况下VS2017使用旧版本的C#
编译器。 You can enable C# 7.0
features by installing Microsoft.Net.Compilers
from NuGet which can be used to compile the code with the latest version of the compiler. 您可以通过从NuGet安装Microsoft.Net.Compilers
来启用C# 7.0
功能,该功能可用于使用最新版本的编译器编译代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.