我有一个强类型的自定义对象列表MyObject,它有一个属性Id和一些其他属性
假设MyObject的Id将其定义为唯一,我想在将新的MyObject添加到集合之前检查我的集合是否还没有Id为1的MyObject对象。
我想使用if(!List.Contains(myObj))但是如何强制只有MyObject的一个或两个属性将其定义为唯一的这一事实?
我可以用IComparable吗?或者我只需要覆盖一个Equals方法,但我需要首先继承一些东西吗?
由于
答案 0 :(得分:46)
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;
}
}
那样做:
return someList.Any(item => item.Id == cmpItem.Id);
请注意,哈希码与相等标准相关。这很重要。
这也使它适用于由具有相同ID定义的相等有用的任何其他情况。如果您有一个要求来检查列表是否有这样的对象,那么我可能会建议您这样做:
{{1}}
答案 1 :(得分:28)
List<T>
使用EqualityComparer<T>.Default
返回的比较器,并根据documentation:
Default属性检查是否 type 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);
答案 2 :(得分:5)
您可以使用LINQ轻松完成此操作。
var result = MyCollection.Any(p=>p.myId == Id);
if(result)
{
//something
}
答案 3 :(得分:2)
您可以覆盖Equals和GetHashCode,实施IEqualityComparer<MyObject>
并在Contains
调用中使用它,或使用Any
等扩展方法
if (!myList.Any(obj => obj.Property == obj2.Property && obj.Property2 == obj2.Property2))
myList.Add(obj2);
答案 4 :(得分:0)
您可以使用IEquatable<T>
。在你的类中实现它,然后检查传递给Equals的T是否与this.Id具有相同的Id。我确信这适用于检查字典中的密钥,但我没有将它用于集合。
答案 5 :(得分:0)
首先使用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的方式。您也可以使用它来处理来自第三方库的对象,因为您无法修改它们的代码。