Collection.Contains() 使用什么来检查现有对象?

发布于 2024-09-17 23:23:20 字数 451 浏览 5 评论 0原文

我有一个强类型的自定义对象列表 MyObject,它有一个属性 Id 以及一些其他属性。

假设 MyObjectId 将其定义为唯一,我想检查我的集合是否还没有一个 MyObject 对象在将新的 MyObject 添加到集合之前,其 Id 为 1。

我想使用 if(!List.Contains(myObj)),但是如何强制执行 MyObject 只有一个或两个属性将其定义为独特的?

我可以使用IComparable吗?或者我只需要重写 Equals 方法?如果是这样的话,我就得先继承一些东西,对吗?

I have a strongly typed list of custom objects, MyObject, which has a property Id, along with some other properties.

Let's say that the Id of a MyObject defines it as unique and I want to check if my collection doesn't already have a MyObject object that has an Id of 1 before I add my new MyObject to the collection.

I want to use if(!List<MyObject>.Contains(myObj)), but how do I enforce the fact that only one or two properties of MyObject define it as unique?

I can use IComparable? Or do I only have to override an Equals method? If so, I'd need to inherit something first, is that right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

意中人 2024-09-24 23:23:20

List.Contains 使用 EqualityComparer.Default,如果类型实现了 IEquatable,则反过来使用 IEquatable,或者否则object.Equals

您可以只实现 IEquatable,但如果这样做的话最好重写 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);

List<T>.Contains uses EqualityComparer<T>.Default, which in turn uses IEquatable<T> if the type implements it, or object.Equals otherwise.

You could just implement IEquatable<T> but it's a good idea to override object.Equals if you do so, and a very good idea to override GetHashCode() if you do that:

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;
    }
}

Note that the hash code relates to the criteria for equality. This is vital.

This also makes it applicable for any other case where equality, as defined by having the same ID, is useful. If you have a one-of requirement to check if a list has such an object, then I'd probably suggest just doing:

return someList.Any(item => item.Id == cmpItem.Id);
怀里藏娇 2024-09-24 23:23:20

List 使用 EqualityComparer.Default 返回的比较器并根据 文档

Default 属性检查是否
T 型实现了
System.IEquatable(Of T) 接口以及,
如果是,则返回 EqualityComparer(Of
T) 使用该实现。
否则,它返回一个
EqualityComparer(Of T) 使用
重写 Object.Equals 和
T提供的Object.GetHashCode。

因此,您可以在自定义类上实现 IEquatable,或者重写 Equals(和 GetHashCode)方法根据您需要的属性进行比较。或者你可以使用 linq:

bool contains = list.Any(i => i.Id == obj.Id);

List<T> uses the comparer returned by EqualityComparer<T>.Default and according to the documentation for that:

The Default property checks whether
type T implements the
System.IEquatable(Of T) interface and,
if so, returns an EqualityComparer(Of
T) that uses that implementation.
Otherwise, it returns an
EqualityComparer(Of T) that uses the
overrides of Object.Equals and
Object.GetHashCode provided by T.

So you can either implement IEquatable<T> on your custom class, or override the Equals (and GetHashCode) methods to do the comparison by the properties you require. Alternatively you could use linq:

bool contains = list.Any(i => i.Id == obj.Id);
檐上三寸雪 2024-09-24 23:23:20

您可以使用 LINQ 轻松完成此操作。

var result = MyCollection.Any(p=>p.myId == Id);
if(result)
{
     //something
}

You can use LINQ to do this pretty easily.

var result = MyCollection.Any(p=>p.myId == Id);
if(result)
{
     //something
}
潇烟暮雨 2024-09-24 23:23:20

您可以重写 Equals 和 GetHashCode,实现 IEqualityComparer 并在 Contains 调用中使用它,或者使用 Any 等扩展方法

if (!myList.Any(obj => obj.Property == obj2.Property && obj.Property2 == obj2.Property2))
   myList.Add(obj2);

You can override Equals and GetHashCode, implement an IEqualityComparer<MyObject> and use that in the Contains call, or use an extension method like Any

if (!myList.Any(obj => obj.Property == obj2.Property && obj.Property2 == obj2.Property2))
   myList.Add(obj2);
各空 2024-09-24 23:23:20

首先使用 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();

这样您就可以定义计算相等性的方式,而无需修改您的类。您还可以使用它来处理来自第三方库的对象,因为您无法修改他们的代码。

First define helper class with 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);
    }
}

Then in your code, just define comparator and use it:

var myComparer = new MyEqualityComparer<MyObject>(delegate(MyObject obj){
    return obj.ID;
});

var result = collection
   .Where(f => anotherCollection.Contains(f.First, myComparer))
   .ToArray();

This way you can define the way how Equality is computed without modifying your classes. You can also use it for processing object from third party libraries as you cannot modify their code.

混浊又暗下来 2024-09-24 23:23:20

您可以使用 IEquatable。在你的类中实现这个,然后检查传递给 Equals 的 T 是否与 this.Id 具有相同的 Id。我确信这适用于检查字典中的键,但我还没有将其用于集合。

You can use IEquatable<T>. Implement this in your class, and then check to see if the T passed to the Equals has the same Id as this.Id. I'm sure this works for checking a key in a dictionary, but I've not used it for a collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文