Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实施IEquatable<;T>;避免列表中的重复项<;T>;_C# - Fatal编程技术网

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