Difference between equal operator and is operator in enums

Viewed 340

Given the following enum,

enum ExampleOptions
{
  OptionA,
  OptionB
}

Is there any real difference between these two statements?

ExampleOptions option = ExampleOptions.OptionA;

bool equals1 = option == ExampleOptions.OptionA; // true
bool equals2 = option is ExampleOptions.OptionA; // true

As far as I can see, the only difference between using == and is is mainly that is expects a constant operand (thus, operation order matters).

I used to use the == operator just because I wanted to avoid ugly statements such as
!(option is ExampleOptions.OptionA).
But, after C#9 was released and the is not operator added; I find is/is not a cleaner and more verbose way to write this kind of statements.

Is there any hidden consequence of deciding which operator to use?

2 Answers

As far as I can see, the only difference between using == and is is mainly that is expects a constant operand (thus, operation order matters).

There's quite a few more differences, for example is allows you to write statements like:

val is ExampleOptions.OptionA or ExampleOptions.OptionB or ExampleOptions.OptionD

rather than the old fashioned statement with || and repeated naming of your variable.

is also (and this is very important!) doesn't call operator ==, it directly checks the instance. This doesn't apply to enums, but if you have an object with a user-defined == operator that doesn't check for null, var != null will most likely crash with an exception, while var is not null will do as you expect.

As for enum comparisons is seems syntactic sugar.

bool equals1 = option == ExampleOptions.OptionA; // true
bool equals2 = option is ExampleOptions.OptionA; // true

Both statements compile to exactly the same IL (tested in .NET5), they invoke the CIL instruction ceq, which I think stands for equality comparison.
So your assumption that there is no functional difference seems correct.

// [115 13 - 115 61] 
IL_0003: ldloc.0      // option
IL_0004: ldc.i4.0
IL_0005: ceq
IL_0007: stloc.1      // equals1

// [116 13 - 116 61]
IL_0008: ldloc.0      // option
IL_0009: ldc.i4.0
IL_000a: ceq
IL_000c: stloc.2      // equals2
Related