将对象添加到ObservableCollection然后查找它时,我有一种奇怪的行为。刚添加之后就找到了,然后使用相同的代码就不再了?
public class TestClass {
public TestClass(string s) {
Str = s;
}
public string Str {
get;
set;
}
}
private ObservableCollection<TestClass> testCollection = new ObservableCollection<TestClass>();
private List<string> newValueList = new List<string> { "one", "two", "three" };
private void Test() {
var tmpList = newValueList.Select(p => new TestClass(p));
foreach (var v in tmpList) {
testCollection.Add(v);
if (testCollection.Contains(v))
Console.WriteLine("YES");
else
Console.WriteLine("NO");
}
foreach (var v in tmpList) {
if (testCollection.Contains(v))
Console.WriteLine("IN");
else
Console.WriteLine("OUT");
}
}
运行此代码将导致输出:YES YES YES OUT OUT OUT
使用 .ToList()
到tmpList
时,您将获得预期的结果。
答案 0 :(得分:2)
您定义了一个运行时不知道如何比较它们的类。所以它假设当它们具有相同的引用而不是Str
时,它们中的两个是相等的。换句话说,当TestClass
和a
是相同的地址时,b
(a
,b
)的两个对象是相等的。如果您想要更改此设置并使a
和b
相等Str
,则应覆盖Equals
和GetHashCode
。 You can read more here或here或here
第一部分:
foreach (var v in tmpList) {
testCollection.Add(v);
if (testCollection.Contains(v))
Console.WriteLine("YES");
else
Console.WriteLine("NO");
}
在这里,您要将v
添加到集合中并检查其中是否有v
,因此它将返回“是”。
第二部分
foreach (var v in tmpList) {
if (testCollection.Contains(v))
Console.WriteLine("IN");
else
Console.WriteLine("OUT");
}
这里你正在寻找v(这不是你的集合中对象的完全相同的引用(因为懒惰的评估每次都在foreach迭代中生成新的实例))你的集合中它将返回“OUT”!
答案 1 :(得分:1)
问题是tmpList
不是一个列表,而是一个&#34;懒惰的&#34;每次foreach
时都会创建新对象的迭代器。
纠正这条线:
var tmpList = newValueList.Select(p => new TestClass(p)).ToList();
答案 2 :(得分:1)
Select方法返回一个IEnumerable对象,该对象在循环中使用时调用GetEnumerator,因此在列表中的每个元素的select方法中为两个循环分别调用Lambda。
Loop1:选择(p =&gt; new TestClass(p)) Loop2:选择(p =&gt; new TestClass(p))
所以只要循环使用tmpList 对于两个循环,执行select语句,调用lambda
因此为每个循环创建了不同的对象集。
您可以通过在lambda表达式中创建断点来验证此行为。
你会看到它被叫6次而不是3次。