簡體   English   中英

如何為HashSet覆蓋Equals和GetHashCode?

[英]How should I override Equals and GetHashCode for HashSet?

可以說我上課了:

    public class Ident
    {
        public String Name { get; set; }
        public String SName { get; set; }
    }

還有一個:

    class IdenNode
    {
        public Ident id { get; set; }
        public List<IdenNode> Nodes { get; set; }

        public IdenNode()
        {
            Nodes = new List<IdenNode>();
        }
    }

我想使用HashSet<IdenNode>的前提是,當且僅當它們的id.Names相等時,它的兩個元素才相同。

因此,我將像下面那樣覆蓋EqualsGetHashCode

        public override bool Equals(object obj)
        {
            IdenNode otherNode = obj as IdenNode;

            return otherNode != null && 
                   otherNode.id != null && 
                   id.Name == otherNode.id.Name;
        }

        public override int GetHashCode()
        {
            if (id != null)
                return id.Name.GetHashCode();
            else
                // what should I write here?
        }

我認為對嗎? 如果是這樣,我應該在GetHashCode放置什么?

更新

能告訴我是OK使用==!=Equals方法是什么? 或者是ReferenceEquals或其他?

另外,我應該重寫運算符==!=嗎?

如果id (或id.Name )為null,則返回0是完全可以的id.Name Nullable<T> (如int? )對於“ null”值返回0。

請記住,兩個對象從GetHashCode()返回相同的值並不意味着相等-它僅意味着兩個對象可能相等。 然而,相反的情況是,兩個“相等”的對象必須返回相同的哈希碼。 您對EqualsGetHashCode定義似乎都滿足了這兩個原則

提防空 你有很多。 請注意StackOverflow不要Equals方法中使用 ==和!=。 通常,在null的情況下,我們返回0作為哈希碼,例如:

public override bool Equals(object obj) {
  // Often we should compare an instance with itself, 
  // so let's have a special case for it (optimization)
  if (Object.ReferenceEquals(obj, this)) 
    return true;

  IdenNode other = obj as IdenNode;

  // otherNode != null line in your code can cause StackOverflow:
  // "!=" calls "Equals" which in turn calls "!=" etc...
  if (Object.ReferenceEquals(null, other))
    return false;

  // Id can be null
  if (Object.ReferenceEquals(id, other.id))
    return true;
  else if (Object.ReferenceEquals(id, null) || Object.ReferenceEquals(other.id, null))
    return false;

  // Let's be exact when comparing strings:
  // i.e. should we use current locale or not etc
  return String.Equals(id.Name, other.id.Name, StringComparison.Ordinal);
}

public override int GetHashCode() {
  // It's typical to return 0 in case of null
  if (Object.ReferenceEquals(null, id))
    return 0;
  else if (Object.ReferenceEquals(null, id.Name)) // <- Name can be null as well!
    return 0;

  return id.Name.GetHashCode();
}

如果是這樣,我應該在GetHashCode中放置什么?

返回零是可以的。 注意,在名稱上定義值相等是一個壞主意; 我知道在美國至少還有其他三個Eric Lippert ,但他們不是我。 實際上,有數百萬甚至數十億人有名字沖突。

請問我可以在Equals方法中使用“ ==”和“!=”嗎? 或者是ReferenceEquals或其他?

我的建議是:在混合參考和價值平等時, 要非常清楚 如果您打算引用相等,請這樣說。

另外,我應該重寫運算符“ ==”和“!=”嗎?

是。 Equals等於一件事而==意味着另一件事是令人困惑的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM