Search code examples
c#equals

Why is there a separate equals method for sets?


In C Sharp .NET there is a Equals method and a SetEquals method. Where is the difference?

Coming from Java, my first thought was that SetEquals is not necessary, just use the Equals method for all objects.


Solution

  • SetEquals doesn't obey the same contract as Equals. In particular it's not symmetric, as the argument is just IEnumerable<T> rather than ISet<T>. This allows you to check for set equality while only having one set. Consider:

    List<int> intList = new List<int> { 1, 2, 3 };
    HashSet<int> intSet = new HashSet<int>(intList);
    

    Now we can use:

    Console.WriteLine(intSet.SetEquals(intList));
    

    ... but we couldn't implement Equals in the same way without enforcing the same behaviour on List<int> and every other IEnumerable<T> implementation.

    Even if we restricted it to other sets, there's the interesting question of what equality really means. For example, consider two HashSet<string> sets which contain the same strings, but have different equality comparers. (Maybe one is case-sensitive and one isn't.) Are those equal, or not? SetEquals manages to avoid such philosophical questions by avoiding trying to be too general.

    What about a HashSet<int> and a SortedSet<int>? Could they ever be equal? They can have the same values - but the ordering of one is undefined.

    Overall, the ideas of Object.Equals and Object.GetHashCode are too broad in my view. Often you want a particular type of equality - and often it makes no sense to compare objects for equality in the first place. This could easily form the subject of a completely different rant, but in the meantime I'm at least glad that .NET didn't try to apply this overly-broad idea to collections. The ability to use SetEquals with a well-defined meaning is more useful, IMO.