What is the correct implementation for GetHashCode() for entity classes?

后端 未结 4 1345
予麋鹿
予麋鹿 2021-02-01 07:45

Below is a sample implementation of overriding Object.Equals() for an entity base class from which all other entities in an application derive.

All entity classes have t

相关标签:
4条回答
  • 2021-02-01 08:30

    You can only correctly implement GetHashCode() if the Id property is immutable for the lifetime of an instance (or at least for the time that its hash needs to be used, such as while the object is in a map or other collection requiring the hash).

    Assuming that it is, you can just use the value of Id as the hash for all valid values and then use a fixed hash for null. I can't remember what the most appropriate is for this, but I would assume a randomly selected value for null(randomly selected prior to compilation, not at runtime) or the median value of valid Id values (i.e. halfway between 0 and int.Max).

    0 讨论(0)
  • 2021-02-01 08:34

    What about using the type as part of the hash code?
    Would this be a good implementation?

    public class Foo
    {
        public int Id { get; set; }
    
        // other properties here
        // ......
    
        public override int GetHashCode()
        {
            int hash = 37;
            hash = hash * 23 + typeof(Foo).GetHashCode();
            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
    
    0 讨论(0)
  • 2021-02-01 08:38

    What Jon Skeet answered is a good solution, however, you might want to add an unchecked code block to allow integer overflowing

    unchecked
    {
      int hash = ...;
      return hash
    }
    

    https://msdn.microsoft.com/en-us/library/khy08726(v=vs.140).aspx

    If neither checked nor unchecked is specified, the default context depends on external factors such as compiler options.

    I'd also like to add, again, that using base.GetHashCode() on POCO's will call the default object.GetHashCode. That's definitely not what you want...

    0 讨论(0)
  • 2021-02-01 08:41

    If you're deriving from something that already overrides GetHashCode I'd implement it as:

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 37;
            hash = hash * 23 + base.GetHashCode();
            hash = hash * 23 + Id.GetHashCode();
            return hash;
        }
    }
    

    A null value of Id will return 0 for Id.GetHashCode().

    If your class just derives from Object, I'd just return Id.GetHashCode() - you do not want to include the object.GetHashCode implementation in your hash code, as that basically ends up being object identity.

    Note that your equality definition won't return true if neither entity has an Id, but the same hashcode will be returned from both objects. You may wish to consider changing your Equals implementation.

    0 讨论(0)
提交回复
热议问题