我应该如何为HashSet重写Equals和GetHashCode?

use*_*838 1 c# hash equals hashset

让我说我上课:

    public class Ident
    {
        public String Name { get; set; }
        public String SName { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

还有一个:

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

        public IdenNode()
        {
            Nodes = new List<IdenNode>();
        }
    }
Run Code Online (Sandbox Code Playgroud)

我想HashSet<IdenNode>大胆地使用它的两个元素是相同的(Equal)当且仅当它们的id.Names是Equal时.

所以,我要覆盖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?
        }
Run Code Online (Sandbox Code Playgroud)

我觉得对吗?GetHashCode如果是这样我应该放什么?

UPDATE

能告诉我是正常使用==,并!=Equals方法?或者可能是ReferenceEquals或其他一些?

另外,我应该重写运营商==!=

D S*_*ley 7

如果id(或id.Name)为null,那么返回0就完全没问题了. Nullable<T>(比如int?)为"null"值返回0.

请记住,返回相同值的两个对象GetHashCode()并不意味着相等 - 它只暗示两个对象可能相等.然而,翻转是两个"相等"对象必须返回相同的哈希码.这两个原则似乎都是通过你对Equals和的定义来实现的GetHashCode


Dmi*_*nko 5

小心空值!你有很多。注意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();
}
Run Code Online (Sandbox Code Playgroud)