我有一个整数值列表;
var items= new List<int>();
items.Add(1);
items.Add(8);
items.Add(14);
items.Add(11);
var sequel=from i in items where i >10 select i;
items[1]=25;
Foreach(var c in sequel)
Console.WriteLine(c);
输出为25 14 11
在我看来,输出应该是14,11。但是,输出实际上是25,14,11。
我的问题是为什么在执行此声明“items [1] = 25;”之后编译器更新“续集”的原因? 在我看来,这些集合是不同的,没有连接。请澄清。
更新:
是的,我读到延迟执行,我的第一个想法是它确实存在。 但是,在调试模式下,我在声明之前看到续集是“14,11”:
items[1]=25;
然后,在此声明之后,“续集”变为“25,14,11”。那么为什么编译器会重新制作查询呢?
答案 0 :(得分:3)
因为LINQ
使用延迟执行。这意味着:
from i in items where i >10 select i;
您只是构建查询。除非您使用foreach
迭代结果或使用迭代查询的方法(例如ToList
和ToArray
,否则它不会被执行。这就是为什么当您更改项目时,查询运行在改变版本上。
有关延迟执行和延迟加载的更多信息,请参阅以下文章:
更新:在Debug
模式下,您实际上评估查询以查看结果。这是在更改项目之前发生的。sequel
没有任何数字,它只是一个查询。没有别的,你只能将数字存储到一个集合,如List
,你在调试器中看到的东西只是一个功能,允许你立即评估查询和显示你的结果。
答案 1 :(得分:2)
这在LINQ中称为Deferred execution
。根据MSDN: -
立即返回值是存储所有内容的对象 执行操作所需的信息。查询 直到对象为止,才执行此方法表示的方法 通过直接调用其GetEnumerator方法或通过调用来枚举 使用foreach
为了获得所需的输出,您需要使用ToList()
或ToArray
来实现您的查询: -
var sequel=(from i in items where i >10 select i).ToList();
<强>更新强>
好的,你必须通过Results View
在调试模式中看到结果吗?因此,只需检查用它给出的描述,Visual Studio说:
扩展结果将枚举IEnumarable
因此,只是为了在调试模式中查看目的,它枚举而不是实际。
答案 2 :(得分:1)
Linq迭代现有的集合 - 它不会复制该集合。如果该集合的内容发生更改,则迭代中的项目将更改。
此外,Linq使用&#34;延迟执行&#34;模型,只有在迭代Linq提供的IEnumerable时才会访问集合中的项目。
如果您想要制作该集合的副本,您可以明确地执行此操作,如下所示:
var sequel=(from i in items where i >10 select i).ToArray();
您也可以使用.ToList()
。
答案 3 :(得分:1)
这是因为LINQ中的懒惰评估。它被称为“延迟执行”,意味着只有在items
循环迭代时才会将条件应用于foreach
。
您的sequel
变量有WhereListIterator
类型。因此,如果您想立即执行,您只需要按ToList()
或ToArray()
迭代此查询:
var sequel = (from i in items where i > 10 select i).ToList();
您的sequel
变量将获得List
类型,您可以通过以下方式设置项目值:
sequel[1] = 25;
在输出中,您将获得14和25个数字。
更改items
不会影响sequel
,因为它是值类型对象的不同集合。
答案 4 :(得分:0)
LINQ具有所谓的延迟执行,这意味着它会根据您的需要在Foreach上加载数据。
看起来像这样:如果你编写一个SQL语句,但没有执行它,它就不会对数据做任何事情。这完全一样。
更多信息,请参阅此处:http://www.codeproject.com/Articles/692847/THREE-Examples-of-Deferred-vs-I