.Contains() 在自定义类对象列表中

Posted

技术标签:

【中文标题】.Contains() 在自定义类对象列表中【英文标题】:.Contains() on a list of custom class objects 【发布时间】:2011-02-07 10:02:20 【问题描述】:

我正在尝试对自定义对象列表使用 .Contains() 函数

这是列表:

List<CartProduct> CartProducts = new List<CartProduct>();

还有CartProduct

public class CartProduct

    public Int32 ID;
    public String Name;
    public Int32 Number;
    public Decimal CurrentPrice;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ID">The ID of the product</param>
    /// <param name="Name">The name of the product</param>
    /// <param name="Number">The total number of that product</param>
    /// <param name="CurrentPrice">The currentprice for the product (1 piece)</param>
    public CartProduct(Int32 ID, String Name, Int32 Number, Decimal CurrentPrice)
    
        this.ID = ID;
        this.Name = Name;
        this.Number = Number;
        this.CurrentPrice = CurrentPrice;
    
    public String ToString()
    
        return Name;
    

所以我尝试在列表中找到类似的购物车产品:

if (CartProducts.Contains(p))

但它忽略了类似的购物车产品,我似乎不知道它检查什么 - ID?还是全部?

提前致谢! :)

【问题讨论】:

【参考方案1】:

默认情况下,引用类型具有引用相等性(即两个实例仅在它们是同一个对象时才相等)。

您需要覆盖 Object.Equals(和 Object.GetHashCode 以匹配)以实现您自己的相等性。 (然后实现一个相等,==,运算符是一个很好的做法。)

【讨论】:

为什么要重写 Object.Equals,这可能会在代码的其他地方产生影响?对我来说,相应地修改搜索代码而不是正在搜索的对象的底层类更有意义...... 你有没有这方面的一些例子,.Find() 或覆盖 Object.Equals/GetHashCode?​​span> @Martin IT 如果您想比较两个 CartProduct 对象在不同位置的行为不同,那将会非常糟糕。 @Rowland - 但我并不是说他必须改变比较的工作方式。如果他想要一个特定的对象,请使用 Contains()。如果他想要任何符合指定条件的对象,请使用 Find() 和合适的谓词(lamda 表达式)......我实际上是在争辩说你根本不接触比较代码 - 你只需调用正确的方法列出您要完成的任务... @Martin 看来我将您的评论误解为类似于“覆盖Contains()”的内容。同意Find() 可以解决这个问题,尽管我建议有一个合适的 equals 方法在其他情况下可能更有用,因为 OP 没有发现同一实体的两个实例的引用是不同的。 【参考方案2】:

如果您想对此进行控制,您需要实现 [IEquatable 接口][1]

[1]:http://This 方法使用默认相等比较器确定相等性,该比较器由对象对 T(列表中值的类型)的 IEquatable.Equals 方法的实现定义。

【讨论】:

【参考方案3】:

你需要实现IEquatable或者覆盖Equals()GetHashCode()

例如:

public class CartProduct : IEquatable<CartProduct>

    public Int32 ID;
    public String Name;
    public Int32 Number;
    public Decimal CurrentPrice;

    public CartProduct(Int32 ID, String Name, Int32 Number, Decimal CurrentPrice)
    
        this.ID = ID;
        this.Name = Name;
        this.Number = Number;
        this.CurrentPrice = CurrentPrice;
    

    public String ToString()
    
        return Name;
    

    public bool Equals( CartProduct other )
    
        // Would still want to check for null etc. first.
        return this.ID == other.ID && 
               this.Name == other.Name && 
               this.Number == other.Number && 
               this.CurrentPrice == other.CurrentPrice;
    

【讨论】:

但是GetHashCode()在哪里? 你不需要实现GetHashCode()。没有它也可以工作。【参考方案4】:

它检查特定对象是否包含在列表中。

使用列表中的 Find 方法可能会更好。

这是一个例子

List<CartProduct> lst = new List<CartProduct>();

CartProduct objBeer;
objBeer = lst.Find(x => (x.Name == "Beer"));

希望有帮助

您还应该看看 LinQ - 这可能有点矫枉过正,但仍然是一个有用的工具......

【讨论】:

Linq 怎么可能会矫枉过正? @MEL - 为什么要在查询和类型推断中混淆这么简单的事情?尽管如此,对于不熟悉 lamdas 的人来说,它可能更具可读性...... +1 很好的清晰示例,显示了不受其他地方更改影响的选项(即,如果 Equals() 方法因任何原因而更改)【参考方案5】:

如果您使用的是 .NET 3.5 或更新版本,您可以使用 LINQ 扩展方法通过 Any 扩展方法实现“包含”检查:

if(CartProducts.Any(prod => prod.ID == p.ID))

这将检查CartProducts 中是否存在具有与p ID 匹配的ID 的产品。您可以在=&gt; 之后放置任何布尔表达式来执行检查。

这还具有适用于 LINQ-to-SQL 查询以及内存中查询的好处,而 Contains 则不行。

【讨论】:

【参考方案6】:

实现override Equals()GetHashCode()

public class CartProduct

    public Int32 ID;
    ...

    public CartProduct(Int32 ID, ...)
    
        this.ID = ID;
        ...
    

    public override int GetHashCode()
    
        return ID;
    

    public override bool Equals(Object obj)
        
            if (obj == null || !(obj is CartProduct))
                return false;
            else
                return GetHashCode() == ((CartProduct)obj).GetHashCode();
        


使用:

if (CartProducts.Contains(p))

【讨论】:

【参考方案7】:

您需要从列表中创建一个对象,例如:

List<CartProduct> lst = new List<CartProduct>();

CartProduct obj = lst.Find(x => (x.Name == "product name"));

该对象通过其属性搜索查找值:x.name

然后您可以使用 List 方法,例如 Contains 或 Remove

if (lst.Contains(obj))

   lst.Remove(obj);

【讨论】:

以上是关于.Contains() 在自定义类对象列表中的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android中自定义动画

在自定义对话框中自定义 Wix 安装程序中的图像

没有在自定义类下拉列表中显示 EDStarRating?

在自定义JsonConverter中反序列化嵌套对象List

打印/修改类对象的特定成员变量,其类定义列表(STL)包含的元素类型

在用户定义的列表中查找具有最大字符数的类对象的项目