.Contains() on a list of custom class objects

I'm trying to use the .Contains() function on a list of custom objects.

This is the list:

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

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

When I try to find a similar cartproduct within the list:

if (CartProducts.Contains(p))

it ignores similar cartproducts and I don't seem to know what it checks on - the ID? or at all?

160049 次浏览

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

您需要重写 Object.Equals(以及要匹配的 Object.GetHashCode)来实现自己的相等性。(实现相等的 ==操作符是一个很好的实践。)

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

[1] : http://This方法通过使用默认的相等比较器来确定相等性,这是由对象的 IEqutable 实现定义的。等于 T (列表中值的类型)的方法。

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

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

您最好使用列表中的 Find 方法。

举个例子

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


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

希望能帮上忙

您还应该关注 LinQ-overkill,尽管如此,它仍然是一个有用的工具..。

如果你正在使用。NET 3.5或更新你可以使用 LINQ 扩展方法通过 Any扩展方法来实现“包含”检查:

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

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

这也有利于处理 LINQ-to-SQL 查询和内存查询,而 Contains不能。

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

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

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


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

该对象通过它们的属性获得搜索值: x.name

然后可以使用“包含”或“删除”等 List 方法

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