Why does the is-operator cause unnecessary boxing?

The compiler is the same in all cases - Roslyn. Different versions produce different IL though. The C# 8 versions don't box, while older ones do.

For example, with 2.9.0 the IL for this snippet :

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 :

    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

and this in Release.

    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. In C# 6 and earlier versions, the constant pattern is supported by the switch statement. Starting with C# 7.0, it's supported by the is statement as well.

By default VS2017 using older version C# compiler. 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.

Tags:

C#

Boxing