C# 实施IEquatable<;T>;避免列表中的重复项<;T>;
我有一个C# 实施IEquatable<;T>;避免列表中的重复项<;T>;,c#,C#,我有一个列表,想从中删除重复项。 如果两个自定义对象的属性:City具有相同的值,则我将它们称为复制对象。 我已经实现了如下IEquatable,但无法从列表中删除重复项 少了什么 public class CustomAddress : IAddress, IEqualityComparer<IAddress> { //Other class members go here //IEqualityComparer members public bool
列表
,想从中删除重复项。如果两个自定义对象的
属性:City
具有相同的值,则我将它们称为复制对象。我已经实现了如下IEquatable,但无法从列表中删除重复项 少了什么
public class CustomAddress : IAddress, IEqualityComparer<IAddress>
{
//Other class members go here
//IEqualityComparer members
public bool Equals(IAddress x, IAddress y)
{
// Check whether the compared objects reference the same data.
if (ReferenceEquals(x, y)) return true;
// Check whether any of the compared objects is null.
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
// Check whether the Objects' properties are equal.
return x.City.Equals(y.City);
}
public int GetHashCode(IAddress obj)
{
// Check whether the object is null.
if (ReferenceEquals(obj, null)) return 0;
int hashAreaName = City == null ? 0 : City.GetHashCode();
return hashAreaName;
}
}
public类客户地址:IAddress,IEqualityComparer
{
//其他班级成员到这里来
//IEqualityComparer成员
公共布尔等于(IAddress x,IAddress y)
{
//检查比较对象是否引用相同的数据。
if(ReferenceEquals(x,y))返回true;
//检查是否有任何比较对象为空。
if(ReferenceEquals(x,null)| | ReferenceEquals(y,null))
返回false;
//检查对象的属性是否相等。
返回x.City等于(y.City);
}
公共int GetHashCode(IADRESS obj)
{
//检查对象是否为空。
if(ReferenceEquals(obj,null))返回0;
int-hashAreaName=City==null?0:City.GetHashCode();
返回hashAreaName;
}
}
我正在使用.NET 3.5来匹配一个特定属性上的重复项,您需要一个比较器
class MyComparer : IEqualityComparer<CustomObject>
{
public bool Equals(CustomObject x, CustomObject y)
{
return x.City.Equals(y.City);
}
public int GetHashCode(CustomObject x)
{
return x.City.GetHashCode()
}
}
编辑:找到了这个可以满足您需要的线程,我想我以前提到过它:
我认为有一个有趣的答案(但不是我是如何做到的)是:
它是一个一行程序,可以满足您的需要,但可能没有其他方法那么有效。仅通过实现
。等于您所做的方式(正确实现的方式),您不会阻止重复项添加到列表中。实际上,您必须手动删除它们
不要使用列表
。它永远不会包含重复项。这是因为List
测试类(CustomObject
)是否实现了IEquatable
,而不是IEquatable
我假设对于重复检查,您使用的是Contains方法,在添加新成员之前,Equals
和GetHashCode
覆盖到位,如果您有需要筛选的现有列表,只需在列表上调用Distinct()
(可通过namespace System.Linq获得)
var noDupes = list.Distinct();
这将给你一个重复的自由序列。如果需要将其作为具体列表,只需在调用末尾添加一个ToList()
var noDupes = list.Distinct().ToList();
另一个答案提到实现一个IEqualityComparer
。当直接重写Equals
和GetHashCode
是不可能的(您不控制源代码)或没有意义(您在这种特殊情况下的相等概念对于类来说不是通用的)时,这非常有用。在这种情况下,请定义比较器,并将比较器的实例提供给Distinct
的重载
最后,如果您要从头开始构建一个列表,并且希望避免插入重复的列表,那么可以使用前面提到的HashSet
。HashSet还接受构造函数中的自定义比较器,因此您可以选择包含该比较器
var mySet = new HashSet<CustomObject>();
bool isAdded = mySet.Add(myElement);
// isAdded will be false if myElement already exists in set, and
// myElement would not be added a second time.
// or you could use
if (!mySet.Contains(myElement))
mySet.Add(myElement);
使用Linq的Distinct()扩展方法。这有点误导,用户不需要比较器,他/她已经重写了Equals和GetHashCode。但这并不意味着答案无效。你什么时候会喜欢外部比较器,而不是像用户那样覆盖Equals和GetHashCode?@Anthony Pegram问得好:)我在另一个项目中查找了我是如何完成它的,并将其剪切粘贴。。。现在你让我思考为什么我没有那样做,哈哈。它确实有效。谢谢你的评论,想知道如果我的CustomAddress类实现了IEqualityComparer为什么不起作用,为什么需要声明一个单独的Comparer类?@iniki,您不希望在被比较的类内实现IEqualityComparer
。至于为什么必须声明一个单独的实例,Distinct
获取您提供的比较器,并使用它获取项hashcodes,然后根据需要进一步测试项之间的相等性。如果您没有通过构造函数提供这样一个实例,它将使用默认的比较器,即检查对象上定义的GetHashCode
和Equals
方法。@iniki,注意:通过将Equals
的覆盖改为IEqualityComparer
的实现,您不再在对象本身中提供有效的Equals
实现,现在Distinct
将通过引用查看类对象的默认相等比较。如果将代码还原为原始代码段,则可以直接使用Distinct()
,而无需自定义比较器实现。
var noDupes = list.Distinct().ToList();
var mySet = new HashSet<CustomObject>();
bool isAdded = mySet.Add(myElement);
// isAdded will be false if myElement already exists in set, and
// myElement would not be added a second time.
// or you could use
if (!mySet.Contains(myElement))
mySet.Add(myElement);
var noDupes = list.DistinctBy(obj => obj.City); // NOT part of BCL