使用 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.Distinct
的 docs 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 接口并覆盖 Equals 和 GetHashCode 方法。
我想让我的 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.Distinct
的 docs 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 接口并覆盖 Equals 和 GetHashCode 方法。