我只是想不通为什么找不到我筛选列表中的项目。我已经简化了这个例子来展示它。我有一个类项目...
public class Item
{
public Item(string name)
{
Name = name;
}
public string Name
{
get; set;
}
public override string ToString()
{
return Name;
}
}
...和一个“项目”类,它应该过滤项目并检查第一个项目是否仍在列表中...
public class Items
{
private IEnumerable<Item> _items;
public Items(IEnumerable<Item> items)
{
_items = items;
}
public List<Item> Filter(string word)
{
var ret = new List<Item>(_items.Where(x => x.Name.Contains(word)));
Console.WriteLine("found: " + ret.Contains(_items.First()));
// found: false
return ret;
}
}
执行代码如下所示:
static void Main(string[] args)
{
string[] itemNames = new string[] { "a", "b", "c" };
Items list = new Items(itemNames.Select(x => new Item(x)));
list.Filter("a");
Console.ReadLine();
}
现在,如果我执行该程序,Console.WriteLine 输出找不到该项目。但是为什么?
如果我将构造函数中的第一行更改为
_items = items.ToList()
然后,它就可以找到它。如果我撤消该行并稍后在 Filter 方法中调用 ToList(),它也找不到该项目?!
public class Items
{
private IEnumerable<Item> _items;
public Items(IEnumerable<Item> items)
{
_items = items;
}
public List<Item> FilteredItems
{
get; set;
}
public List<Item> Filter(string word)
{
var ret = new List<Item>(_items.Where(x => x.Name.Contains(word)));
_items = _items.ToList();
Console.WriteLine("found: " + ret.Contains(_items.First()));
// found: false
return ret;
}
}
为什么执行 lambda 表达式的时间和地点不同,为什么找不到该项目?我不明白!
最佳答案
原因是延迟执行。
您将 _items
字段初始化为
itemNames.Select(x => new Item(x));
这是一个查询,而不是该查询的答案。每次迭代 _items
时,都会执行此查询。
所以在 Filter
方法的这一行中:
var ret = new List<Item>(_items.Where(x => x.Name.Contains(word)));
枚举源数组并为每个字符串创建一个 new Item(x)
。这些项目存储在您的列表 ret
中。
当您之后调用 Contains(_items.First())
时,First()
再次 执行查询 在 _items
中,为每个源字符串创建新 Item
实例。
由于 Item
的 Equals
方法可能未被覆盖并执行简单的引用相等性检查,所以从第二次迭代返回的第一个 Item
Item
的实例与列表中的实例不同。
关于c# - IEnumerable 中的项目不等于 List 中的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41266178/