GetHashCode when one of properties can be null

324 Views Asked by At

I am currently trying to figure out how to deal with situation, where I want to use some object as a key in dictionary, therefore I need it to have overriden GetHashCode and Equals methods. The problem is that one of the properties of my object is nullable.

public class Car
{
   public int Id { get; set; }
   public CarBodyType Type { get; set; }

   public int? LifeSpanInYears { get; set; }


   public override bool Equals(object o)
   {
      // ...
   }

   public override int GetHashCode()
   {
      var result = base.GetHashCode();
      result = (result * 397) ^ this.Id.GetHashCode();
      result = (result * 397) ^ this.Type.GetHashCode();

      // Here ... What is the best approach? Currently, result will be 1 if LifeSpanInYears is null.
      result = (result * 397) ^ (this.LifeSpanInYears?.GetHashCode() ?? 0);

      return result;
   }
}

What is the best approach when dealing with possible null value of one of the properties? My opinion is that this would be the best approach.

if (this.LifeSpanInYears.HasValue)
{
   result = (result * 397) ^ this.LifeSpanInYears.GetHashCode();
}

At least I will get rid of the problem, where result of GetHashCode is 1 everytime any of the nullable properties is null.

What's your take on this?

Thank you so much for your response.

1

There are 1 best solutions below

2
Theodor Zoulias On

You could consider using the built-in HashCode struct:

public override int GetHashCode()
{
    HashCode hashCode = new();
    hashCode.Add(this.Id);
    hashCode.Add(this.Type);
    hashCode.Add(this.LifeSpanInYears);
    return hashCode.ToHashCode();
}

...or:

public override int GetHashCode()
{
    return HashCode.Combine(this.Id, this.Type, this.LifeSpanInYears);
}

It takes care of the nullable values. You don't have to do anything special for them.

I would expect it to be slower than your multiply+XOR approach, but it should produce a better quality hashcode. The source code of the HashCode struct is here.

Note: the HashCode type is available from .NET Core 2.1 and later.