使用 IEquatable<Student> 使列表<Student> 可区分

Make List<Student> Distinctable with IEquatable<Student>

我想让我的 Class 存储在列表中时可以排序(按年龄)。

我读了这篇文章:IComparable Vs IComparer 并使我的 class 可排序。

public class Student : IComparable<Student>
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public int CompareTo(Student other)
    {
        if (this.Age > other.Age)
        {
            return 1;
        }
        else if (this.Age < other.Age)
        {
            return -1;
        }
        else
        {
            return 0;
        }
    }
}

List students = new List();

// And Filling students

students.Sort();

现在,我想让我的 class 与众不同,我的意思是当我调用 .Distinct() 时,它会删除重复的学生 ID。

我读了IEquatable VS IEqualityComparer 和排序一样(没有参数)我希望调用 .Distinct() 没有传递参数。

public class Student : IEquatable<Student>
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        public bool Equals(Student other)
        {
            if (this.ID == other.ID)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
}

List students = new List();

// And Filling students

students.Distinct();

但是当我使用这个时什么也没有发生。 为什么?

以及如何实现 IEquatable 并使用 Distinct() 而不传递参数?

与所有其他 LINQ 方法不同 return 值而不是修改原始集合。

修复 - 将结果分配给变量或 ToList 并分配回学生。

看看 Enumerable.Distinctdocs says:

The default equality comparer, Default, is used to compare values of the types that implement the IEquatable generic interface. To compare a custom data type, you need to implement this interface and provide your own GetHashCode and Equals methods for the type.

我没看到你的 Student class:

  • ...覆盖 Object.GetHashCode(...).
  • ...覆盖 Object.Equals(...)

另一方面,Enumerable.Distinct returns:

...an unordered sequence that contains no duplicate values. It uses the default equality comparer, Default, to compare values.

因此,您需要将结果设置为一个变量:

var x = enumerable.Distinct();

考虑使用 HashSet<T>

也许您希望 collection 包含 独特的元素 。如果是这种情况,请不要将元素存储在常规 collection 中以便稍后调用 Enumerable.Distinct(),而是直接使用 HashSet<T>

一旦您修复了 Student class 覆盖上述所有方法的问题,您就可以按如下方式存储学生:

HashSet<Student> studentSet = new HashSet<Student();
studentSet.Add(new Student { ID = 1, Name = "Matías", Age = 32 });

// HashSet<T>.Add returns true if it could add the whole element. 
// In our case, this if statement will never enter!
if(studentSet.Add(new Student { ID = 1, Name = "Matías", Age = 32 }))
{
}

您应该实现 IEquable 接口并覆盖 EqualsGetHashCode 方法。