# V3229. The 'GetHashCode' method may return different hash codes for equal objects. It uses an object reference to generate a hash for a variable. Check the implementation of the 'Equals' method.

The analyzer has detected that the `GetHashCode` result depends on the hash code of a reference to an object, while the `Equals` result depends on that object's comparison logic, which differs from comparing two references. This mismatch can break the contract: if `Equals` considers two objects equal, they should also have the same hash code.

Breaking the contract of the `GetHashCode` and `Equals` methods can cause several functions and data structures to malfunction, including:

- collections like `HashSet` and `Dictionary`;
- LINQ methods such as `Union`, `Intersect`, and others.

The example:

    public HashSet<Value> Values { get; private set; }  = new();
    ....
    public override bool Equals(object obj)
    {
      if (obj is not CustomObject other)
        return false;

      return Values.SequenceEqual(other.Values);
    }

    public override int GetHashCode()
    {
      return Values.GetHashCode();
    }

The hash code from the reference to the `Values` collection is used as the return value of `GetHashCode` for some class, while `Equals` compares the contents of that collection element-by-element using `SequenceEqual`.

Option 1. Simplify the object comparison:

    public HashSet<Value> Values { get; private set; } = new();
    ....
    public override bool Equals(object obj)
    {
      if (obj is not CustomObject other)
        return false;

      return Values.Equals(other.Values);
    }

    public override int GetHashCode()
    {
      return Values.GetHashCode();
    }

Option N2. Ensure that the algorithm in `GetHashCode` also considers the hash codes of the collection elements:

    public readonly HashSet<Value> Values { get; private set; } = new();
    ....
    public override bool Equals(object obj)
    {
      if (obj is not CustomObject other)
        return false;

      return Values.SequenceEqual(other.Values);
    }

    public override int GetHashCode()
    {
      return Values.Aggregate(0,
               (hash, val) =>   (hash * 397)
                              ^ (val?.GetHashCode() ?? 0));
    }

The `Aggregate` call creates a single hash code for the collection by iterating through its elements and updating `hash` at each step according to the function that was passed as the second argument.

Note. The `GetHashCode` function must run quickly, and option N2 may not meet that requirement.