c# - 为什么 is-operator 会导致不必要的装箱?

标签 c# boxing

documentationis 运算符(expr is constant)的常量模式匹配状态:

The constant expression is evaluated as follows:

  1. If expr and constant are integral types, the C# equality operator determines whether the expression returns true (that is, whether expr == constant).

  2. 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/

相关文章:

c# - LINQ GroupBy,同时保留所有对象字段

.net - PowerShell Invoke-Sqlcmd - 不返回 DataTable 或 DataSet

c# - Monotouch.Dialog 两个表

c# - 将两个复选框绑定(bind)到 MVVM 中的可为 null 的 bool 属性

vb.net - 将 .GetValueOrDefault(0) 和 If(variable, 0) 与可空类型一起使用有什么区别吗?

c# - 为什么我不能修改拆箱转换的结果?

c# - 转换到基类是否涉及装箱和拆箱

c# - 为什么不能使用 is 运算符来区分 bool 和 Nullable<bool>?

c# - Visual Studio 项目 : How to include a reference for one configuration only?

c# - 为什么以这种方式转换为类型不是有效语法?