Search code examples
c#gethashcode

Equals is used. GetHashCode is not


I have implemented the class below:

public class carComparer : IEqualityComparer<Car>
    {
        public bool Equals(Car car1, Car car2)
        {
                if (car1 == null || car2 == null)
                    return false;

                return (car1.description == car2.description);
        }

        public int GetHashCode(Car car)
        {
            unchecked 
            {
                int hash = 17;
                hash = hash * 29 + car.id.GetHashCode();
                hash = hash * 29 + car.description.GetHashCode();
                return hash;
            }
        }

    }

Now see this:

Car p1 = new Car() { id = Guid.NewGuid(), description = "Test1" };
        Car p2 = new Car() { id = Guid.NewGuid(), description = "Test1" };
        Car p3 = new Car() { id = Guid.NewGuid(), description = "Test1" };
        Car p4 = new Car() { id = Guid.NewGuid(), description = "Test1" };
        var hash = new HashSet<Car>();
        hash.Add(p1);
        hash.Add(p2);

        var hash2 = new HashSet<Car>();
        hash2.Add(p3);
        hash2.Add(p4);

        var carComparer = new CarComparer();
        Assert.That(hash, Is.EquivalentTo(hash2).Using(carComparer));

I put breakpoints in .equals and .hashcode. Equals is used; but GetHashCode is not. Why?


Solution

  • You are comparing two HashSet using NUnit Is.EquivalentTo. There is no reason for it to call GetHashCode - it basically compares two collections for equality of its members. That's why GetHashCode is never called and Equals is called to compare two items from different HashSets for equality. Your hashsets could as well be lists or any other enumerable - that doesn't change anything when comparing two collections.

    You might expect GetHashCode to be called when you add item to HashSet - but it's not so, because at this point your carComparer is not yet known - you don't pass it to HashSet constructor. If you will do it like this:

    var hash = new HashSet<Car>(new carComparer());
    

    Then GetHashCode would be called when you add new item to corresponding HashSet.