Distinct 方法不适用于 class 与覆盖等于

Distinct method doesn't work for class with overriden Equals

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

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?

您还必须覆盖 GetHashCode

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

Distinct首先比较hashcodes,应该比实际的Equals计算得更快。 Equals 只有在两个实例的哈希码 相等 时才会进一步评估。

您需要在 MyClass 中实现 IEquatable<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;
    }
}

Distinct docs:

Returns distinct elements from a sequence by using the default equality comparer to compare values.

让我们看看what the default equality comparer does:

The Default property checks whether type T implements the System.IEquatable<T> interface and, if so, returns an EqualityComparer<T> that uses that implementation. Otherwise, it returns an EqualityComparer<T> that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

所以基本上,要完成这项工作,您可以:

  • 同时实施 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);
    }
}