如果之后更新源,为什么要更新 linq 结果?
Why is linq result updated, if a source is updated afterwards?
我有一个整数值列表;
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;" 后更新 "sequel"?
在我看来,这些系列是不同的并且没有关联。请说明。
更新:
是的,我读到有关延迟执行的信息,我的第一个想法是确实如此。
但是,在调试模式下,我看到 sequel 在声明之前是“14, 11”:
items[1]=25;
然后,在这条语句之后"sequel"变成了“25,14,11”。那么为什么编译器要重新生成查询?
Linq 遍历现有集合 - 它不会复制该集合。如果该集合的内容发生变化,迭代中的项目也会发生变化。
此外,Linq 使用 "Deferred Execution" 模型,其中只有在迭代 Linq 提供的 IEnumerable 时才会访问集合中的项目。
如果你想制作一个集合的副本,你可以明确地这样做,就像这样:
var sequel=(from i in items where i >10 select i).ToArray();
您也可以使用 .ToList()
.
因为LINQ
使用延迟执行。这意味着这里:
from i in items where i >10 select i;
您只是在构建查询。它不会执行,除非您使用 foreach
迭代结果或使用迭代查询的方法,例如 ToList
和 ToArray
。这就是为什么当您更改项目时,查询运行在更改后的版本上。
有关延迟执行和延迟加载的更多信息,请参阅以下文章:
更新: 在 Debug
模式下,您实际上是在 评估 查询以查看 results.This 发生在之前你更改项目。sequel
不包含任何数字,它只是一个 query.Nothing 否则,你只能将数字存储到集合中,例如 List
,你在调试器中看到的是只是一个允许您立即评估查询并显示结果的功能。
这在 LINQ 中称为 Deferred execution
。根据 MSDN:-
The immediate return value is an object that stores all the
information that is required to perform the action. The query
represented by this method is not executed until the object is
enumerated either by calling its GetEnumerator method directly or by
using foreach
因此,要获得所需的输出,您需要使用 ToList()
或 ToArray
来实现您的查询,如下所示:-
var sequel=(from i in items where i >10 select i).ToList();
更新:
好的同意,你一定在调试模式下通过Results View
看到了结果吧?所以只要检查它给出的描述,Visual Studio 说:
Expanding the results will enumerate the IEnumarable
所以只是为了在调试模式下查看,它会枚举而不是实际。
LINQ 具有所谓的延迟执行,这意味着它会根据需要加载数据,在您的情况下是在 Foreach 上。
这样看:如果你写了一个SQL-语句,但不执行它,它不会对数据做任何事情。这完全一样。
更多信息,请参见此处:http://www.codeproject.com/Articles/692847/THREE-Examples-of-Deferred-vs-I
这是因为 LINQ 中的惰性求值。它被称为 "Deferred Execution" 并且意味着条件将仅在 items
被 foreach
循环迭代时应用于 items
。
您的 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
,因为它是值类型对象的不同集合。
我有一个整数值列表;
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;" 后更新 "sequel"? 在我看来,这些系列是不同的并且没有关联。请说明。
更新:
是的,我读到有关延迟执行的信息,我的第一个想法是确实如此。 但是,在调试模式下,我看到 sequel 在声明之前是“14, 11”:
items[1]=25;
然后,在这条语句之后"sequel"变成了“25,14,11”。那么为什么编译器要重新生成查询?
Linq 遍历现有集合 - 它不会复制该集合。如果该集合的内容发生变化,迭代中的项目也会发生变化。
此外,Linq 使用 "Deferred Execution" 模型,其中只有在迭代 Linq 提供的 IEnumerable 时才会访问集合中的项目。
如果你想制作一个集合的副本,你可以明确地这样做,就像这样:
var sequel=(from i in items where i >10 select i).ToArray();
您也可以使用 .ToList()
.
因为LINQ
使用延迟执行。这意味着这里:
from i in items where i >10 select i;
您只是在构建查询。它不会执行,除非您使用 foreach
迭代结果或使用迭代查询的方法,例如 ToList
和 ToArray
。这就是为什么当您更改项目时,查询运行在更改后的版本上。
有关延迟执行和延迟加载的更多信息,请参阅以下文章:
更新: 在 Debug
模式下,您实际上是在 评估 查询以查看 results.This 发生在之前你更改项目。sequel
不包含任何数字,它只是一个 query.Nothing 否则,你只能将数字存储到集合中,例如 List
,你在调试器中看到的是只是一个允许您立即评估查询并显示结果的功能。
这在 LINQ 中称为 Deferred execution
。根据 MSDN:-
The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach
因此,要获得所需的输出,您需要使用 ToList()
或 ToArray
来实现您的查询,如下所示:-
var sequel=(from i in items where i >10 select i).ToList();
更新:
好的同意,你一定在调试模式下通过Results View
看到了结果吧?所以只要检查它给出的描述,Visual Studio 说:
Expanding the results will enumerate the IEnumarable
所以只是为了在调试模式下查看,它会枚举而不是实际。
LINQ 具有所谓的延迟执行,这意味着它会根据需要加载数据,在您的情况下是在 Foreach 上。
这样看:如果你写了一个SQL-语句,但不执行它,它不会对数据做任何事情。这完全一样。
更多信息,请参见此处:http://www.codeproject.com/Articles/692847/THREE-Examples-of-Deferred-vs-I
这是因为 LINQ 中的惰性求值。它被称为 "Deferred Execution" 并且意味着条件将仅在 items
被 foreach
循环迭代时应用于 items
。
您的 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
,因为它是值类型对象的不同集合。