如何在没有任何数字作为字段的情况下覆盖 GetHashCode()?

Posted

技术标签:

【中文标题】如何在没有任何数字作为字段的情况下覆盖 GetHashCode()?【英文标题】:How do I override GetHashCode() without any numbers as fields? 【发布时间】:2017-02-01 14:05:17 【问题描述】:

所有显示如何覆盖 Equals(object)GetHashCode() 的资源都使用数字字段来实现 GetHashCode() 方法:

Implementing the Equals MethodWhat's the best strategy for Equals and GetHashCode? Why is it important to override GetHashCode when Equals method is overridden?

但是,在我的课堂上,我没有任何数字字段。它是树中的一个节点,引用其父节点、子节点和接口作为数据:

public class Node

    private IInterface myInterface;
    private Node parent;
    private List<Node> children = new List<Node>();

    public override bool Equals(object obj)
    
        if (obj == null || GetType() != obj.GetType())
        
            return false;
        
        var node = (Node)obj;
        return myInterface == node.myInterface;
    

    public override int GetHashCode()
    
        ???
    

我应该用什么设置哈希码?

【问题讨论】:

【参考方案1】:

根据Equals 实现,两个Nodes 实例当且仅当它们的myInterface 相等时才相等:

public override bool Equals(object obj)

    if (obj == null || GetType() != obj.GetType())
    
        return false;
    
    var node = (Node)obj;

    // instances are equal if and only if myInterface's are equal
    return myInterface == node.myInterface;

这就是为什么myInterfaceGetHashCode 的唯一来源:

 public override int GetHashCode()
 
    return null == myInterface ? 0 : myInterface.GetHashCode();
 

PS已编辑,感谢 Kris Vandermotten)通常,在比较潜在的时间/资源之前检查 Equals 实现中的 ReferenceEquals 是一个好习惯消费myInterfaces:

 public override bool Equals(object obj) 
   // Easy tests: 
   // 1. If "this" and "obj" are in fact just the same reference?
   // 2. Since `Node` (or Equals) is not sealed, the safiest is to check types 
   if (object.ReferenceEquals(this, obj))
     return true;
   else if (null == obj || other.GetType() != GetType()) 
     return false;

   // Potentially time/resource cosuming (we don't know IInterface implementation)
   return ((Node) obj).myInterface == myInterface;
 

【讨论】:

您的 Equals 方法不检查类型相等性。正因为如此,只有在没有继承自 Node 的类型时,人们才会认为它是正确的。如果Nodepublic,这意味着它必须是sealed。此外,但这是一个单独的问题,我可能还会实现 IEquatable&lt;Node&gt;,主要是出于性能原因。 @Evorlor: 1. 在开始比较myInterfaces(可以是时间/资源)之前测试引用相等性(实例等于自身)通常是一个好习惯cosuming) 2. as 专为此类比较而设计;在这种情况下不要使用 GetType 和强制转换。 @Kris Vandermotten:我同意你的观点,实现IEquatable&lt;Node&gt; 接口是一个好主意。但是,Equals 比较节点(某些图?),而不是实现;如果派生类 MyNode 想要更改策略,它应该覆盖 EqualsGetHashCode 如果派生类可以覆盖Equals,那么您最终可能会遇到a.Equals(b) 为真而b.Equals(a) 不为真的情况,这很奇怪。避免这种情况的最简单方法当然是制作Nodesealed。如果这不可能,检查类型相等性(就像 OP 所做的那样)可能会有所帮助。 @Kris Vandermotten:你是对的(我已经编辑了答案);检查类型似乎是最简单的方法,除非整个 Node 类或至少 GetHashCodeEqualssealed

以上是关于如何在没有任何数字作为字段的情况下覆盖 GetHashCode()?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不覆盖当前数据的情况下更新 Mongoose 中的混合类型字段?

是否可以在没有代码覆盖率工具作为入口点的情况下收集代码覆盖率数据?

如何在没有`jq`的情况下获取JSON字段值?

如何在不覆盖 ModelForm 中的字段定义的情况下将 ManyToManyField 小部件更改为 CheckboxSelectMultiple

如何在没有 `jq` 的情况下获取 JSON 字段值?

如何在没有指数表示法的情况下将浮点数作为字符串获取?