我有一个名为accessoire的课程:
class accessoire
{
public int value1 { get; set; }
public string Value2 { get; set; }
}
然后我有一个该产品的列表
List<accessoire> accessoires
我有一个用户界面,用户从DataGridview中选择他想要的产品,当他选择它时,启动一个将该项添加到列表中的事件:
private void ProductBrowser_OnItemAdded(Accessoire item)
{
if (Cart.Contains(item))
{
MessageBox.Show("Produit deja ajoutée au panier ! ");
}
else
{
Cart.Add(item);
ProductView.Rows.Add(item.Ref, item.Name, Function.CatName(item.Cat), item.SellPrice, "1", Convert.ToDouble(item.SellPrice) * Convert.ToDouble(item.QtetoSell));
TotalPriceSet();
MessageBox.Show("Produit Ajouté !");
}
}
这不起作用,但当我将其更改为:
private void ProductBrowser_OnItemAdded(Accessoire item)
{
var InList = Cart.Find(product => product.Ref == item.Ref);
if (Cart.Contains(InList))
{
MessageBox.Show("Product already in list ! ");
}
else
{
Cart.Add(item);
ProductView.Rows.Add(item.Ref, item.Name, Function.CatName(item.Cat), item.SellPrice, "1", Convert.ToDouble(item.SellPrice) * Convert.ToDouble(item.QtetoSell));
TotalPriceSet();
MessageBox.Show("product added !");
}
}
它有效,但我仍然想知道为什么第一个代码不能正常工作它继续将该项添加到列表中?在其他方面,方法.Contains()
如何工作?什么检查项目是否是或不是列表?
答案 0 :(得分:3)
它在列表中找不到对象的原因是因为它是参考比较,比较对象的实例而不是值。您的类的两个实例在其属性中具有相同的值,但如果您比较它们,它们就不相等:
accessoire item1 = new accessoire();
item1.value1 = 1;
item1.value2 = "one";
accessoire item2 = new accessoire();
item2.value1 = 1;
item2.value2 = "one";
if(item1 == item2) MessageBox.Show("Same");
else MessageBox.Show("Different");
当您从列表中选择要与之比较的项目时,您将拉出列表中存在的特定实例。
答案 1 :(得分:0)
您需要实现accessoire的Equals方法才能正确比较其中的所有属性/字段。 Equals的默认实现使用ReferenceEquals,它仅在两个实例实际上相同时才有效。
答案 2 :(得分:0)
if (Cart.Contains(item))
是平等匹配
如果object.Equals(T)
不满意,则会失败。这意味着即使是字符串中的空格,最小的更改也将返回false。如果您有两个相同类的实例,那么您也会得到错误的结果。包含必须完全引用item
。
var InList = Cart.Find(product => product.Ref == item.Ref)
是属性匹配。这意味着只要.Ref匹配,产品/项目的其他属性都可以不同。我认为Ref是一个主键,这就是为什么你在Find()
返回错误项目的结果中没有遇到问题的原因。
您可以通过覆盖Equals
的{{1}}来解决差异,但我不推荐它。它可以在以后进行调试。
答案 3 :(得分:0)
只需实现equals方法
Cart
答案 4 :(得分:0)
您正在进行参考比较,并且您的第一个示例中的引用不匹配,但在您的第二个示例中执行。您可能想要进行相等比较。两个对象的值是否相同。
下面是使用用于相等比较的各种方法实现的类。您只需要修改它们以适合您的目的。
// IEquatable<T> provides typed equality comparing
class accessoire : IEquatable<accessoire>
{
public int Value1 { get; set; }
public string Value2 { get; set; }
// you can override Equals.
public override bool Equals(object obj)
{
return this.Equals(obj as accessoire);
}
// this comes from IEquatable<T>
public bool Equals(accessoire other)
{
if (ReferenceEquals(null, other))
{
return false;
}
// return the comparison that makes them equal.
return
this.Value1.Equals(this.Value1) &&
this.Value2.Equals(this.Value2);
}
public override int GetHashCode()
{
unchecked
{
int hash = 37;
hash *= 23 + this.Value1.GetHashCode();
hash *= 23 + this.Value2.GetHashCode();
return hash;
}
}
// allows you to check equality with the == operator
public static bool operator ==(accessoire left, accessoire right)
{
if (ReferenceEquals(left, right))
{
return true;
}
if ((oject)left == null || (object)right == null)
{
return false;
}
return left.Equals(right);
}
public static bool operator !=(accessoire left, accessoire right)
{
return !left.Equals(right);
}
}