Right way to implement GetHashCode for this struct

前端 未结 7 1859
庸人自扰
庸人自扰 2021-02-13 06:13

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 St         


        
相关标签:
7条回答
  • 2021-02-13 06:45

    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.

    0 讨论(0)
  • 2021-02-13 06:46

    Something like this:) with a different prime number:)

    public override int GetHashCode()
    {
        unchecked  
        {
            int hash = 23;
            // Suitable nullity checks etc, of course :)
            hash = hash * 31 + Start.GetHashCode();
            hash = hash * 31 + End.GetHashCode();
            return hash;
        }
    }
    

    This is not the fastest implementation but it produces a good hash code. Joshua bloch indicates that as well and you also calculate the performance, ^ is usually faster. correct me if i m wrong.

    See Jon Skeets impl for c# :

    0 讨论(0)
  • 2021-02-13 06:49

    Just as it might help someone in the future that uses visual studio pro (not sure if this also exist in community edition)

    • Select the desired properties (in your case all)
    • Press refacoring (CTRL + . or right click "Quick actions an refactorings")
    • Now you can select to implement Equals or GetHashcode (and probably it always takes the best known MS way to do it)
    0 讨论(0)
  • 2021-02-13 06:56

    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;
        }
    }
    
    0 讨论(0)
  • 2021-02-13 06:57

    I would trust Microsoft's implementation of GetHashCode() at the tuples and use something like this without any stupid magic:

    public override int GetHashCode()
    {
        Tuple.Create(x, y).GetHashCode();
    }
    
    0 讨论(0)
  • 2021-02-13 06:58

    Since DateTime.GetHashCode is internally based on Ticks, what about this:

        public override int GetHashCode()
        {
            return unchecked((int)(Start.Ticks ^ End.Ticks));
        }
    

    Or, since you seem to be interested by the date parts (year, month, day), not the whole thing, this implementation uses the number of days between the two dates and should give almost no collision:

            public override int GetHashCode()
            {
                return unchecked((int)Start.Date.Year * 366 + Start.Date.DayOfYear + (End.Date - Start.Date).Days);
            }
    
    0 讨论(0)
提交回复
热议问题