Search code examples
c#.nethashsetgethashcode

HashSet on collections of objects


I have an object of type T which implements IEquatable<T> (methods Equals and GetHashCode are implemented). I use these objects in a HashSet<T>. But for my development I need to upgrade the elements of this hash set to collections of T objects (lists or arrays will both work, for instance I will use HashSet<List<T>>). These collections (List<T> for instance) have default Equals and GetHashCode methods, but how can I override them such that two collections are said to be equal if and only if they are sequentially equal? And how to get an appropriate GetHashCode? Is this functionality already present in .Net in some way? I could define a new type TT which wraps a List<T> for instance, and implements IEquatable<TT> and use Enumerable.SequenceEqual in the Equals method. But what about GetHashCode? Thanks!


Solution

  • HashSet<T> has a constructor which takes an IEqualityComparer<T>. You can use this to customise how the HashSet<T> compares its elements.

    Something like:

    public class ListEqualityComparer<T> : IEqualityComparer<List<T>>
    {
        public bool Equals(List<T> x, List<T> y)
        {
            if (x is null && y is null)
                return true;
            if (x is null || y is null)
                return false;
        
            return x.SequenceEqual(y);
        }
    
        public int GetHashCode(List<T> obj)
        {
            if (obj is null)
                return 0;
        
            var hashCode = new HashCode();
            foreach (var item in obj)
            {
                hashCode.Add(item);
            }
            return hashCode.ToHashCode();
        }
    }
    

    Then:

    var hashSet = new HashSet<List<YourType>>(new ListEqualityComparer<YourType>());