请考虑以下事项:
class Bind
{
public string x { get; set; }
public string y { get; set; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection<Bind> cX = new ObservableCollection<Bind>();
ObservableCollection<Bind> cY = new ObservableCollection<Bind>();
cX.Add(new Bind { x = "a", y = "1" });
cX.Add(new Bind { x = "b", y = "2" });
cY.Add(new Bind { x = "a", y = "1" });
foreach (var i in cX)
{
if (!cY.Contains(i)) { lv.Items.Add(i); } //lv is a ListView control
}
}
}
为什么会将x = "a", y = "1"
添加到ListView
?
如果我将ObservableCollection
更改为List
或Collection
,则会执行相同操作。
答案 0 :(得分:18)
'Contains'方法使用Equals on对象,这只是检查内存地址是否不同。
考虑将您的班级更改为此...
class Bind : IEquatable<Bind> {
public string x { get; set; }
public string y { get; set; }
public bool Equals(Bind other)
{
return x == other.x && y == other.y;
}
}
您的循环将访问您班级中强类型的Equals方法,这将导致您所追求的行为。
注意:字符串类ALSO继承自T的IEquatable,这允许相等运算符对字符串的内容而不是字符串的地址进行操作。
答案 1 :(得分:3)
因为您已将该值设置为CX:
cX.Add(new Bind { x = "a", y = "1" });
和CY:
cY.Add(new Bind { x = "a", y = "1" });
这些是不同的对象。
如果您想查看是否存在给定密钥,则需要更改为字典或使用Linq。
答案 2 :(得分:2)
因为"a" != "a"
。至少,并非总是如此。
Contains()
将检查内存地址,而不是实际内容。您不能两次插入同一个对象,"a"
与"a"
不是同一个对象(至少,不在此处)。
答案 3 :(得分:2)