63

In the case of using enums, is it better to use:

if (enumInstance.Equals(MyEnum.SomeValue))

or to use

if (enumInstance == MyEnum.SomeValue)

Are their any important considerations using one vs the other?

ToddBFisher
  • 11,370
  • 8
  • 38
  • 54
  • I feel like this has probably been answered before, I just can't find where. If it has been answered let me know and I will deleted this question – ToddBFisher Jul 05 '13 at 15:20
  • 9
    pretty much *every* question asked on SO has been asked here before... there should be a badge for asking a truly unique question. – Michael Bray Jul 05 '13 at 15:21
  • http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals – jAC Jul 05 '13 at 15:22
  • 1
    There's a small thread about it on [MSDN](http://social.msdn.microsoft.com/Forums/vstudio/en-us/644790c4-4004-4c66-aa78-b4f64f411beb/enumequals-vs-) – Pierre-Luc Pineault Jul 05 '13 at 15:22
  • 1
    @MatthewWatson: haha yup... I have one of those too. :) – Michael Bray Jul 05 '13 at 15:28
  • When you call enumInstance.Equals the enum parameter must be boxed as Equals takes object as a parameter, so to avoid the boxing it is better to use ==, if you can – Alexandr Mihalciuc Jul 05 '13 at 15:37

4 Answers4

61

If the compile-time type of enumInstance is the enum type, you're fine with ==.

If the compile-time type of enumInstance is Enum, ValueType or Object, you need to use Equals. (You'll get a compile-time error if you try to use == in that case.)

Note that your enum currently violates .NET naming conventions - it would normally be MyEnum.Value.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • in the case that there is an enum declared that has multiple properties/values set to the same number, does .Equals() convert it to it's numerical representation before comparing? With that, is it against best practices to have multiple enum properties/values have the same underlying numerical value? – ToddBFisher Jul 05 '13 at 15:29
  • @ToddBFisher: There *is* only a numerical representation. Two names for the same value still actually have the same value. It can be useful in some cases to have multiple names with the same value, but it's rare and should only be used when you really want them to mean the same thing. One example would be if a previous version had a typo in one name, and you wanted to fix the typo without breaking old source code. – Jon Skeet Jul 05 '13 at 15:33
  • This caused a very sneaky bug, involving a `params Func[]` comparison extension method on a generic collection. – Michael Oct 14 '15 at 01:46
34

Using == instead of Equals is a bit quicker, there is no need to box enums and no functions calls needed here is sample c# code and generated MSIL for it:

 class Program
    {
        static void Main(string[] args)
        {
            var instance = MyEnum.First;

            if (instance == MyEnum.First)
            {
                Console.WriteLine("== Called");
            }

            if (instance.Equals(MyEnum.First))
            {
                Console.WriteLine("Equals called");
            }

        }     
    }

    enum MyEnum { First = 99, Second = 100}

MSIL:

IL_0000:  nop
  IL_0001:  ldc.i4.s   99
  IL_0003:  stloc.0
  IL_0004:  ldloc.0
  IL_0005:  ldc.i4.s   99
  IL_0007:  ceq
  IL_0009:  ldc.i4.0
  IL_000a:  ceq
  IL_000c:  stloc.1
  IL_000d:  ldloc.1
  IL_000e:  brtrue.s   IL_001d
  IL_0010:  nop
  IL_0011:  ldstr      "== Called"
  IL_0016:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_001b:  nop
  IL_001c:  nop
  IL_001d:  ldloc.0
  IL_001e:  box        ConsoleApplication1.MyEnum
  IL_0023:  ldc.i4.s   99
  IL_0025:  box        ConsoleApplication1.MyEnum
  IL_002a:  callvirt   instance bool [mscorlib]System.Object::Equals(object)
  IL_002f:  ldc.i4.0
  IL_0030:  ceq
  IL_0032:  stloc.1
  IL_0033:  ldloc.1
  IL_0034:  brtrue.s   IL_0043
  IL_0036:  nop
  IL_0037:  ldstr      "Equals called"
  IL_003c:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_0041:  nop
  IL_0042:  nop
  IL_0043:  ret

As you can see == generates ceq instruction, Equals method performes boxing and callvirt

Alexandr Mihalciuc
  • 2,537
  • 15
  • 12
  • 1
    If this is your only criterion for choosing this answer, be wary that you may be prematurely optimising chaps! – Nick Bull Sep 10 '19 at 08:45
8

As an extension to Jon Skeet's old answer, it is true that you get a compilation error when you compare Enum == YourActualEnum.Value, however when you do Enum == Enum, which compiles fine, it return false all the time.

public class TestClass
{
    public bool TestMethod1()
    {
        bool Result = false;

        Enum l_Value = TEST_ENUM.TEST_VALUE_1;

        Enum l_Check_Value = TEST_ENUM.TEST_VALUE_1;

        Result = l_Value == l_Check_Value;

        return Result;
    }

    public bool TestMethod2()
    {
        bool Result = false;

        TEST_ENUM l_Value = TEST_ENUM.TEST_VALUE_1;

        TEST_ENUM l_Check_Value = TEST_ENUM.TEST_VALUE_1;

        Result = l_Value == l_Check_Value;

        return Result;
    }

    public bool TestMethod3()
    {
        bool Result = false;

        Enum l_Value = TEST_ENUM.TEST_VALUE_1;

        Enum l_Check_Value = TEST_ENUM.TEST_VALUE_1;

        Result = l_Value.Equals(l_Check_Value);

        return Result;
    }

    public enum TEST_ENUM
    {
        TEST_VALUE_1,
        TEST_VALUE_2,
        TEST_VALUE_3
    }
}

if you try the following on a test app you'll get the following

Console.WriteLine("Method 1 result: {0}", myClass.TestMethod1());

Console.WriteLine("Method 2 result: {0}", myClass.TestMethod2());

Console.WriteLine("Method 3 result: {0}", myClass.TestMethod3());

you will get the following results

Method 1 result: False Method 2 result: True Method 3 result: True

If you wonder why would you ever compare Enum against Enum....I discovered it while trying to be smart while creating an EnumConverter and a FlagConvert for a WPF project. There you receive only an object value as parameter and for the flag converter specifically i wanted to provide a special text for when no flag was selected (i.e. the enum has a value of 0 which has no static member for it).

Nothing else worked (including value.Equals(0), value.Equals((int)0) ) except this:

l_Source_Type = value.GetType();

if (l_Source_Type.IsDefined(typeof(FlagsAttribute)))
{
    Enum l_Value = (Enum)value;

    Enum l_Check_Value = (Enum)Enum.ToObject(l_Source_Type, 0);

    if (l_Value.Equals(l_Check_Value))
    {
        return String.Empty;
    }
}
Krease
  • 15,805
  • 8
  • 54
  • 86
user1464603
  • 437
  • 4
  • 8
  • 1
    Mind explaining the downvote? As i said I cannot comment and I added this to help other people that have the same issue that I have, as I ended up on this answer while searching to solve my issue. – user1464603 Apr 13 '18 at 15:28
4

There is a case that the other answers here have not mentioned that may help others.

With c# the underlying type of an enum is an integral. Because it is an integral, you can logically OR the enums together.

When using either of the above methods for equality will fail if enums are logically OR'd together.

So for some special cases, such as using enums as flags, you will need to logically AND the case you are testing for with first prior to checking for equality.

if ((enumInstance & MyEnum.SomeValue).Equals(MyEnum.SomeValue))

or

if ((enumInstance & MyEnum.SomeValue) == MyEnum.SomeValue)

Strictly speaking it's safest to use "==" with enums.

A complete list of possible enum types can be found here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/enum

user3416682
  • 113
  • 2
  • 8