。包含自定义类对象列表的()


95

我正在尝试.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?还是全部?

提前致谢!:)

Answers:


119

您需要实现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;
    }
}

4
但是哪里GetHashCode()呢?
锡安比

1
您不需要实现GetHashCode()。没有它就可以工作。
user890332

141

如果您使用的是.NET 3.5或更高版本,则可以使用LINQ扩展方法来实现对扩展方法的“包含”检查Any

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

这将检查是否存在CartProductsID与ID相匹配的产品p。您可以在后面放置任何布尔表达式=>以执行检查。

这还具有处理LINQ-to-SQL查询和内存查询的优势Contains


12

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

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

这是一个例子

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

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

希望有帮助

您还应该看一下LinQ-也许对此有些大材小用,但是仍然是一个有用的工具...


1
Linq怎么会过分杀人?
Mel Gerats 2010年

@MEL-为什么要混入查询并为这种简单的操作键入推论?,虽然说,这可能是更容易阅读的人不熟悉lamdas ...
马丁米兰

+1明确的示例,该示例显示了不会受到其他地方更改(即,由于Equals()某种原因而更改了该方法)的选项
Rowland Shaw 2010年

4

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

您需要重写Object.Equals(并Object.GetHashCode匹配)以实现自己的相等性。(然后,实现等价==运算符是一种好的做法。)


1
为什么要覆盖Object.Equals,这可能会在代码的其他地方产生影响?对我来说,相应地修改搜索代码更有意义,而不是在搜索对象的基础类……
Martin Milan 2010年

您是否有一些示例,例如.Find()或重写Object.Equals / GetHashCode?
Jan Johansen

如果您希望两个CartProduct对象的比较在不同位置的行为不同,则@Martin IT将非常混乱。
罗兰·肖

1
@Rowland-但我并不是说他必须改变比较的方式。如果他想要一个特定的对象,请使用Contains()。如果他想要任何符合指定条件的对象,请使用带有适当谓词(lamda表达式)的Find()...实际上,我认为您根本不使用比较代码-您只需在列出您要完成的任务...
Martin Milan 2010年

1
@Martin似乎我将您的评论误解为“ override Contains()”。同意Find()可以解决该问题,尽管我会建议在其他情况下使用适当的equals方法可能更为有用,因为OP并未发现相同实体的两个实例的引用是不同的。
罗兰·肖

1

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

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

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

该对象通过其属性搜索得到外观值:x.name

然后,您可以使用包含或删除之类的列表方法

if (lst.Contains(obj))
{
   lst.Remove(obj);
}

0

实施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))

-1

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.