Distinct()如何在对象列表上工作?

Ati*_*MVP 2 c# linq distinct

var people = new List<Person>
{
    new Person
    {
        Id = 1,
        Name = "Atish"
    },
    new Person
    {
        Id = 2,
        Name = "Dipongkor"
    },
    new Person
    {
        Id = 1,
        Name = "Atish"
    }
};

Console.WriteLine(people.Distinct().Count());
Run Code Online (Sandbox Code Playgroud)

为什么输出3

为什么不是2

Dou*_*las 6

引用类型的默认相等比较器是引用相等,它仅true在两个对象引用指向同一实例时返回(即通过单个new语句创建).这与测试值相等的值类型不同,true如果所有数据字段相等(如您的情况中的两个),则返回值.更多信息:Equality Comparisons(C#编程指南).

如果要更改此行为,则需要IEquatable<T>在类型上实现通用接口,以便比较实例的属性是否相等.Distinct随后,运营商将自动选择此实施并产生预期结果.

编辑:以下是IEquatable<Person>您班级的示例实现:

public class Person : IEquatable<Person>
{
    public int Id { get; set; }
    public int Name { get; set; }

    public bool Equals(Person other)
    {
        if (other == null)
            return false;

        return Object.ReferenceEquals(this, other) ||
            this.Id == other.Id &&
            this.Name == other.Name;
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        int hash = this.Id.GetHashCode();
        if (this.Name != null)
            hash ^= this.Name.GetHashCode();
        return hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

从覆盖和运营商的指导方针(重点补充):==!=

默认情况下,运算符==通过确定两个引用是否指示同一对象来测试引用相等性.因此,引用类型不必实现运算符==以获得此功能.当一个类型是不可变的,也就是说,实例中包含的数据不能被改变,重载运算符==来比较值的相等而不是引用相等可能是有用的,因为作为不可变对象,只要它们可以被认为是相同的具有相同的价值.在非不可变类型中覆盖运算符不是一个好主意==.