7

I have created two enums and I know they are not the same but still I think it makes sense they would be equal since their string representation as well as their numeral representation are equal (and even the same...).

In other words : I would like the first test to pass and the second one to fail. In reality however, they both fail. So : when are two enums in C# equal? Or is there anyway to define the equals operator in C#?

Thanks!

    public enum enumA {one, two}

    public enum enumB {one, two}

    [Test]
    public void PreTest()
    {           
    Assert.AreEqual(enumA.one,enumB.one);
    Assert.AreSame(enumA.one, enumB.one);
    }

UPDATE : 1) So the answers so far all compare representations, be it ints or strings. The enum itself is always unequal I gather? No means to define equality for it?

Peter
  • 47,963
  • 46
  • 132
  • 181
  • Duplicate: http://stackoverflow.com/questions/1410131/comparing-two-enum-types-for-equivalence – Robert Harvey Nov 05 '09 at 21:25
  • @Robert : thanks for the link, interesting and related. Clearly not duplicate : it asks for the value of an enum. – Peter Nov 05 '09 at 21:30

7 Answers7

15

Enums are strongly typed in C#, hence enumA.one != enumB.one. Now, if you were convert each enum to their integer value, they would be equal.

Assert.AreEqual((int)enumA.one, (int)enumB.one);

Also, I'd like to challenge the statement that because they have the same integer or string representation that they should be the same or equals. Given two enumerations NetworkInterface and VehicleType, it would not be logical for C# or the .Net Framework to allow NetworkInterface.None to equal VehicleType.None when compared as enumeration, by either value or string. However, if the developer cast the strongly typed enumeration to an integer or string, there is nothing the language or framework can do to stop the two from being equals.

To further clarify, you cannot override MyEnum.Equals in order to provide a different equality method. .Net enums are not quite the first class citizens they are in later versions of Java, and I wish that C# allowed for richer interactions with Enums.

user7116
  • 63,008
  • 17
  • 141
  • 172
  • 1
    be careful here, this is only true if the ordinal position is the same. – Tim Jarvis Nov 05 '09 at 21:27
  • 1
    thanks. But the != operator isNOT the one I am afterm rather equals(). Even different strongly typed types can be equal I thought, or is that not true? – Peter Nov 05 '09 at 21:35
  • @Peter: Enumerations are structs, moreover, you cannot overload any of their methods. Also I used != as more of a verb than an actual code snippet. @Tim: indeed, this is for his case and his case only. – user7116 Nov 05 '09 at 21:39
  • Enumerations are Value Types, to clarify my above. – user7116 Nov 05 '09 at 21:42
  • It's too bad that MS used the same name for the virtual `Equals(Object)` method as is used for the type-specific overloads; things would have been much clearer if the former were named `EquivalentTo`. As things are, `Equals` only defines an equivalence relation if one casts the operand to `Object`. Otherwise, (4.0).Equals(4.0f) is true [4.0f gets converted to, and compared as, `double`], but (4.0f).Equals(4.0) is false [4.0 gets converted to, and compared as, `Object`]. Similar situations apply comparing enum types and integers. – supercat Mar 21 '13 at 17:40
  • If the virtual method were named `EquivalentTo`, then if `X` and `Y` are both numeric or enum variables with the value four, then `X.Equals(Y)` could be expected to yield true when type coercion would permit meaningful comparison, and refuse to compile when it wouldn't; `X.EquivalentTo(Y)` meanwhile would be expected to do a much stricter comparison [such that `(4.0).EquivalentTo(4.0f)` or even `(4.0m).EquivalentTo(4.00m)` would return false. A bit late now for MS to change it, though. – supercat Mar 21 '13 at 17:51
3

I refer you to the C# Language Specification v3.0, from which this quote has been extracted from the Enum section on page 29:

"Each enum type has a corresponding integral type called the underlying type of the enum type. An enum type that does not explicitly declare an underlying type has an underlying type of int. An enum type’s storage format and range of possible values are determined by its underlying type. The set of values that an enum type can take on is not limited by its enum members. In particular, any value of the underlying type of an enum can be cast to the enum type and is a distinct valid value of that enum type."

The .AreEqual method is really testing equivalence while the second tests identity. So, simply cast each one to its underlying type (in this case, int) and then do the comparison.

public enum enumA { one, two }
public enum enumB { one, two }
[Test]
public void PreTest()
{
        Assert.AreEqual((int)enumA.one,(int)enumB.one);
        Assert.AreSame(enumA.one, enumB.one);
}
Tim Jarvis
  • 18,465
  • 9
  • 55
  • 92
cpkilekofp
  • 101
  • 3
2

Unlike Java, C# does not provide any facility for adding methods (such as operator==()) to an enum.

What I have done in the past when needing smarter enums is create an XHelper class (where X is the name of the enum), and I put all of the methods on it. Thus something like this:

public static bool EnumAHelper.EqualsEnumB(EnumA enumA, EnumB enumB)
{
    return (int)enumA == (int)enumB;
}

Though, I do not recall running into a case where I needed two different enums to signify the same thing.

Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
  • Very good remark (after though). I am rewriting an existing class that I want to be compatible, so it's enums should be the same too. – Peter Nov 05 '09 at 22:31
1

If you want them to match, cast them to int

Assert.AreEqual((int)enumA.one,(int)enumB.one);

would pass because they are both the first listed. If you wanted them to match because they both say "one" then you need to use reflection.

Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • 2
    I think, you could do this, to check the string values: Assert.AreEqual(enumA.one.ToString(), enumB.one.ToString()); – Jonas Nov 05 '09 at 21:25
1

To be honest, Equality is not straight forward most of the time.

I would be inclined to create a helper class that implements IEqualityComparer (and any other equality tests, IsSame() for example) and use that.

Tim Jarvis
  • 18,465
  • 9
  • 55
  • 92
0
    public enum enumA {one = 1, two = 2}

    public enum enumB {one = 1, two = 2}

    [Test]
    public void PreTest()
    {                       
        Assert.AreEqual((int)enumA.one, (int)enumB.one);
        // I don't think this one will ever pass
        Assert.AreSame(enumA.one, enumB.one); 
    }
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
0

You could try casting them:

Assert.AreEqual((int)enumA.one, (int)enumB.one);
Jonas
  • 4,454
  • 3
  • 37
  • 45