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

How do I override GetHashCode() without any numbers as fields?

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

实现equals方法Equals和GetHashCode的最佳策略是什么?为什么在重写Equals方法时重写GetHashCode很重要?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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()
    {
        ???
    }
}

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


根据Equals的实现,两个Node的实例是相等的,只要它们的myInterface是相等的:

1
2
3
4
5
6
7
8
9
10
11
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的唯一来源:

1
2
3
4
 public override int GetHashCode()
 {
    return null == myInterface ? 0 : myInterface.GetHashCode();
 }

P.S.(编辑,感谢Kris Vandermotten)通常,在比较可能消耗时间/资源的myInterface之前,检查Equals实现中的ReferenceEquals是一个很好的做法:

1
2
3
4
5
6
7
8
9
10
11
12
 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;
 }