Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right way to implement GetHashCode for this struct

Tags:

c#

.net

hash

I want to use a date range (from one date to another date) as a key for a dictionary, so I wrote my own struct:

   struct DateRange
   {
      public DateTime Start;
      public DateTime End;

      public DateRange(DateTime start, DateTime end)
      {
         Start = start.Date;
         End = end.Date;
      }

      public override int GetHashCode()
      {
         // ???
      }
   }

What's the best way to implement GetHashCode so no two objects of a differing range will generate the same hash? I want hash collisions to be as unlikely as possible, though I understand Dictionary<> will still check the equality operator which I will also implement, but didn't want to pollute the example code too much. Thanks!

like image 777
Mike Christensen Avatar asked Oct 18 '11 21:10

Mike Christensen


People also ask

Do I need to implement GetHashCode?

Why is it important to override GetHashCode ? It s important to implement both equals and gethashcode, due to collisions, in particular while using dictionaries. if two object returns same hashcode, they are inserted in the dictionary with chaining. While accessing the item equals method is used.

Should I override GetHashCode?

If you're implementing a reference type, you should consider overriding the Equals method if your type looks like a base type, such as Point, String, BigNumber, and so on. Override the GetHashCode method to allow a type to work correctly in a hash table.

How does GetHashCode work in C#?

GetHashCode method of the base class uses reflection to compute the hash code based on the values of the type's fields. In other words, value types whose fields have equal values have equal hash codes.

What is the purpose of GetHashCode?

A hash code is a numeric value which is used to insert and identify an object in a hash-based collection. The GetHashCode method provides this hash code for algorithms that need quick checks of object equality.


2 Answers

You can use the method from Effective Java as Jon Skeet shows here. For your specific type:

public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        hash = hash * 23 + Start.GetHashCode();
        hash = hash * 23 + End.GetHashCode();
        return hash;
    }
}
like image 126
Mark Byers Avatar answered Sep 21 '22 14:09

Mark Byers


In C# 7 you can do this:

public override int GetHashCode() => (Start, End).GetHashCode();

The ValueTuple is available in .NET Framework 4.7 and .NET Core, or via NuGet.

Not sure how well it performs, but I would be surprised if any custom code would beat it.

like image 26
l33t Avatar answered Sep 20 '22 14:09

l33t