不同的方法不适用于覆盖等于

时间:2017-06-07 08:27:21

标签: c# distinct ienumerable equals

我用覆盖的Equals创建了类。问题是,Distinct方法对我的班级不起作用。

class MyClass
{
    public int Item1 { get; private set; }
    public int Item2 { get; private set; }

    public MyClass(int item1, int item2)=>(Item1,Item2)=(item1,item2); 


    public override bool Equals(object obj)
    {
        var other = obj as MyClass;

        if (other == null)
        {
            return false;
        }

        return (this.Item1 == other.Item1 && this.Item2 == other.Item2);
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyClass x = new MyClass(1, 0);
        MyClass y = new MyClass(1, 0);
        var list = new List<MyClass>();
        list.Add(x);
        list.Add(y);


        bool b = x.Equals(y));  //True
        var distincts = list.Distinct(); //Doesn't work, contains both
    }
}

我该如何解决这个问题?为什么它不能使用我的Equals in Distinct?

3 个答案:

答案 0 :(得分:3)

Distinct docs

  

使用默认相等比较器来比较值,从序列中返回不同的元素。

让我们看看what the default equality comparer does

  

Default属性检查类型T是否实现System.IEquatable<T>接口,如果是,则返回使用该实现的EqualityComparer<T>。否则,它会返回使用T 提供的 EqualityComparer<T>Object.Equals覆盖的Object.GetHashCode

所以基本上,要做到这一点,你要么:

  • 同时实施GetHashCode
  • 实施IEquatable<T>
  • 调用接受自定义相等比较器的Distinct的重载。

如果我是你,我会选择第二个,因为你需要更改最少的代码。

class MyClass: IEquatable<MyClass> {
    ...

    public bool Equals(MyClass obj)
    {
        if (obj == null)
        {
            return false;
        }

        return (this.Item1 == obj.Item1 && this.Item2 == obj.Item2);
    }
}

答案 1 :(得分:2)

您还必须覆盖GetHashCode

public override int GetHashCode()
{
    return Item1; // or something
}

Distinct首先比较哈希码,这些哈希码应该比实际Equals更快地计算。如果两个实例的哈希码相等,则Equals只会被进一步评估。

答案 2 :(得分:1)

您需要在IEquatable<MyClass>中实施MyClass并提供您自己的GetHashCodeEquals方法的实施。

有关详细信息,请参阅this

class MyClass
{
    public int Item1 { get; private set; }
    public int Item2 { get; private set; }

    public MyClass(int item1, int item2)=>(Item1,Item2)=(item1,item2); 


    public override bool Equals(object obj)
    {
        var other = obj as MyClass;

        if (other == null)
        {
            return false;
        }

        return (this.Item1 == other.Item1 && this.Item2 == other.Item2);
    }

    public override int GetHashCode()
    {

        return this.Item1;
    }
}