The documentation of constant pattern matching with the is
-operator (expr is constant
) states:
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.
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:
.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):
.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. 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. InC# 6
and earlier versions, the constant pattern is supported by theswitch
statement. Starting withC# 7.0
, it's supported by theis
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With