Collection.Contains() 使用啥来检查现有对象?
Posted
技术标签:
【中文标题】Collection.Contains() 使用啥来检查现有对象?【英文标题】:What does Collection.Contains() use to check for existing objects?Collection.Contains() 使用什么来检查现有对象? 【发布时间】:2011-04-07 23:15:26 【问题描述】:我有一个自定义对象的强类型列表MyObject
,它有一个属性Id
,以及其他一些属性。
假设MyObject
的Id
将其定义为唯一的,我想在添加我的新集合之前检查我的集合是否还没有Id
为1 的MyObject
对象MyObject
收藏。
我想使用if(!List<MyObject>.Contains(myObj))
,但我如何强制执行MyObject
的只有一个或两个属性将其定义为唯一的事实?
我可以使用IComparable
?还是我只需要覆盖Equals
方法?如果是这样,我需要先继承一些东西,对吗?
【问题讨论】:
【参考方案1】:List<T>.Contains
使用 EqualityComparer<T>.Default
,如果类型实现它,则反过来使用 IEquatable<T>
,否则使用 object.Equals
。
你可以只实现IEquatable<T>
,但如果你这样做,覆盖object.Equals
是个好主意,如果你这样做,覆盖GetHashCode()
是一个非常好主意:
public class SomeIDdClass : IEquatable<SomeIDdClass>
private readonly int _id;
public SomeIDdClass(int id)
_id = id;
public int Id
get return _id;
public bool Equals(SomeIDdClass other)
return null != other && _id == other._id;
public override bool Equals(object obj)
return Equals(obj as SomeIDdClass);
public override int GetHashCode()
return _id;
请注意,哈希码与相等标准相关。这是至关重要的。
这也使它适用于任何其他情况,即通过具有相同 ID 定义的相等性是有用的。如果您有一个要求来检查列表是否有这样的对象,那么我可能会建议这样做:
return someList.Any(item => item.Id == cmpItem.Id);
【讨论】:
【参考方案2】:List<T>
使用EqualityComparer<T>.Default
返回的比较器,并根据documentation 进行:
Default 属性检查是否 类型 T 实现 System.IEquatable(Of T) 接口和, 如果是,则返回 EqualityComparer(Of T) 使用该实现。 否则,它返回一个 EqualityComparer(Of T) 使用 覆盖 Object.Equals 和 Object.GetHashCode 由 T 提供。
因此,您可以在自定义类上实现IEquatable<T>
,或覆盖Equals
(和GetHashCode
)方法以根据您需要的属性进行比较。或者,您可以使用 linq:
bool contains = list.Any(i => i.Id == obj.Id);
【讨论】:
我会选择 Linq 语句。如果你愿意,你可以实现一个扩展方法 Contains您可以使用 LINQ 轻松完成此操作。
var result = MyCollection.Any(p=>p.myId == Id);
if(result)
//something
【讨论】:
甜蜜。好点子!对你们俩+1。随心所欲地花钱。 我要把这一切都吹到帽子上。【参考方案4】:您可以覆盖 Equals 和 GetHashCode,实现 IEqualityComparer<MyObject>
并在 Contains
调用中使用它,或者使用像 Any
这样的扩展方法
if (!myList.Any(obj => obj.Property == obj2.Property && obj.Property2 == obj2.Property2))
myList.Add(obj2);
【讨论】:
+1,这是一个很好的高性能解决方案,尤其是在您使用集合或字典时。 (说到 Equals/GetHashCode 点)【参考方案5】:首先用 IEqualityComparer 定义辅助类。
public class MyEqualityComparer<T> : IEqualityComparer<T>
Func<T, int> _hashDelegate;
public MyEqualityComparer(Func<T, int> hashDelegate)
_hashDelegate = hashDelegate;
public bool Equals(T x, T y)
return _hashDelegate(x) == _hashDelegate(y);
public int GetHashCode(T obj)
return _hashDelegate(obj);
然后在你的代码中,定义比较器并使用它:
var myComparer = new MyEqualityComparer<MyObject>(delegate(MyObject obj)
return obj.ID;
);
var result = collection
.Where(f => anotherCollection.Contains(f.First, myComparer))
.ToArray();
通过这种方式,您可以在不修改类的情况下定义 Equality 的计算方式。您也可以使用它来处理来自第三方库的对象,因为您无法修改他们的代码。
【讨论】:
【参考方案6】:您可以使用IEquatable<T>
。在你的类中实现它,然后检查传递给 Equals 的 T 是否与 this.Id 具有相同的 Id。我确信这适用于检查字典中的键,但我没有将它用于集合。
【讨论】:
以上是关于Collection.Contains() 使用啥来检查现有对象?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 中 required 和 @required 有啥区别。它们之间有啥区别,我们啥时候需要使用它们?
c#啥时候应该使用List,啥时候应该使用arraylist?
你啥时候把 Javascript 放在 body 里,啥时候放在 head 里,啥时候使用 doc.load? [复制]