【问题标题】:.Contains() on a list of custom class objects.Contains() 在自定义类对象列表中
【发布时间】: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?还是全部?

提前致谢! :)

【问题讨论】:

    标签: c# list class contains


    【解决方案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);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-04-07
            • 1970-01-01
            • 1970-01-01
            • 2023-03-29
            • 2013-01-12
            • 2015-05-08
            • 2011-01-09
            • 2012-06-07
            相关资源
            最近更新 更多