﻿# 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`](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=net-10.0) and [`Equals`](https://learn.microsoft.com/en-us/dotnet/api/system.object.equals?view=net-8.0) 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:

```cpp
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:

```cpp
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:

```cpp
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\.