(from n in numbers where n == 5 select n).ToList();
如果没有这些括号,就无法调用ToList()方法。我该如何向别人解释这行代码的作用(我只能说它预编译了查询,但我不知道这是否完全正确)。
from n in numbers where n = 5 select n
实际上是 numbers.Where(n => n == 5)
的语法糖。因此,你使用 LINQ 表达式对数字列表进行筛选,仅保留等于 5 的数字。
然而,LINQ 是一种惰性求值的方式。这意味着由 numbers.Where (n => n == 5)
返回的对象(一个 IEnumerable)不是等于五的数字列表。只有在尝试访问 IEnumerable 的元素时才会创建该列表。
ToList
将此 IEnumerable 的内容复制到一个列表中,这意味着必须立即评估表达式。
.ToList()
可能只是指 n
。如果你直接使用扩展方法,可能会更容易向不熟悉LINQ的人解释。
numbers.Where(number => number == 5).ToList();
对于像这样的简单情况,这变得更加明显。
在我看来,这似乎是一个用括号包装的 LINQ 表达式,其结果将是 IEnumerable<int>
,随后调用 IEnumerable<T>
扩展方法 ToList<T>()
。
我认为在这种情况下,调用 ToList<T>
强制表达式立即计算,从本质上放弃了任何惰性计算。
Eric White 在 使用 LINQ 进行延迟(和急切)求值的好文章
它将一个 IEnumerable<t>
转换为一个 List<t>
更熟悉LINQ的人可能会纠正我,但据我所知,LINQ表达式本身并不一定在您“执行”之前被计算。因此,如果您想立即评估它,那么您将像这样调用ToList()。(这也将其从IEnumerable转换为IList,而不仅仅是评估它。)
当然,它被括在括号中,以告诉编译器ToList()的完整范围。
括号将表达式分组成逻辑上的原子值。
这类似于算术运算
1 + 1 * 2 = 4
错误!(= 3)
(1 + 1) * 2 = 4
正确!