linq & distinct, implementing the equals & gethashcode

流过昼夜 提交于 2019-11-29 10:22:22

You need to override the Equals(object) method:

public override bool Equals(object obj) {
    return Equals(obj as parent);
}

The object.Equals method (unlike EqualityComparer<T>.Default) does not use the IEquatable interface. Therefore, when you write object.Equals(c1, other.c1), it doesn't call your Child.Equals(Child) method.

You don't absolutely need to do that for parent as well, but you really should.

Either you do what SLaks suggests, or you use EqualityComparer<child>.Default in your parent class to use your IEquatable<child> implementation:

  public bool Equals(parent other)
  {
   return object.Equals(id, other.id) &&
    object.Equals(blah1, other.blah1) &&
    EqualityComparer<child>.Default.Equals(c1, other.c1);
 }

When adding the calculating the hash you might want to try something like

hash ^= id.GetHashCode();

Not sure if that is what is causing your issue.

There are several things to get right here. If I'm going to implement any aspect of equality in a class such as GetHashCode, overriding == or IEquatable, I always use the following pattern.

  1. Override Equals
  2. Override GetHashCode
  3. Implement IEquatable<T> which means implementing Equals(T)
  4. Implement !=
  5. Implement ==

So, if I had a class named ExpiryMonth with properties Year and Month, this is how that implementation would look. It's a fairly mindless task now to adapt for other types of classes.

I have based this pattern on several other stackoverflow answers which all deserve credit, but which I haven't tracked along the way.

By always implementing all of these elements together, it ensures proper equality operations in a variety of contexts including dictionaries and Linq operations.

    public static bool operator !=(ExpiryMonth em1, ExpiryMonth em2)
    {
        if (((object)em1) == null || ((object)em2) == null)
        {
            return !Object.Equals(em1, em2);
        }
        else
        {
            return !(em1.Equals(em2));
        }
    }
    public static bool operator ==(ExpiryMonth em1, ExpiryMonth em2)
    {
        if (((object)em1) == null || ((object)em2) == null)
        {
            return Object.Equals(em1, em2);
        }
        else
        {
            return em1.Equals(em2);
        }
    }
    public bool Equals(ExpiryMonth other)
    {
        if (other == null) { return false; }
        return Year == other.Year && Month == other.Month;
    }
    public override bool Equals(object obj)
    {
        if (obj == null) { return false; }
        ExpiryMonth em = obj as ExpiryMonth;
        if (em == null) { return false; }
        else { return Equals(em); }
    }
    public override int GetHashCode()
    {
        unchecked // Overflow is not a problem
        {
            var result = 17;
            result = (result * 397) + Year.GetHashCode();
            result = (result * 397) + Month.GetHashCode();
            return result;
        }
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!