【问题标题】:One "simple" problem about building LINQ query drives me crazy关于构建 LINQ 查询的一个“简单”问题让我抓狂
【发布时间】:2020-01-30 21:53:02
【问题描述】:
IEnumerable<char> query = "Not what you might expect";

query = query.Where(c=>c!='a');
query = query.Where(c=>c!='e');
query = query.Where(c=>c!='i');
query = query.Where(c=>c!='o');
query = query.Where(c=>c!='u');

foreach(char c in query) Console.Write(c);

简单的 LINQ 查询构建。 我的问题是,为什么所有这些查询都会执行?为什么不只有最后一个? 这是如何编译的,程序如何知道返回查询初始化? 希望你能理解我的问题。

我知道这段代码有效且直观,但幕后发生了什么?

【问题讨论】:

  • 您将每个过滤器的结果分配回查询变量。为什么每个人都不执行?
  • 将其视为StringBuilder,通过调用builder.Append(value).Append(another),您将收集需要在最终字符串中的所有数据,通过调用.ToString(),您实际上构建了一个新字符串。
  • 我不确定我是否理解您的问题。最后一行确实执行了。评估 Where 语句的“时间”将在 ForEach 循环内的 GetEnumerator 期间进行。
  • 您是否在问为什么每个Where 都会为foreach 的每次迭代执行?这可能是因为 LINQ 被延迟评估。
  • 延迟执行

标签: c# linq


【解决方案1】:

如果你这样写,只有最后一个查询会执行:

IEnumerable<char> source = "Not what you might expect";

query = source.Where(c=>c!='a');
query = source.Where(c=>c!='e');
query = source.Where(c=>c!='i');
query = source.Where(c=>c!='o');
query = source.Where(c=>c!='u');

foreach(char c in query) Console.Write(c);

只执行最后一个查询,因为每一行替换上面分配的查询。

另一方面,你的例子等价于:

IEnumerable<char> source = "Not what you might expect";

query = source.Where(c=>c!='a').Where(c=>c!='e').Where(c=>c!='i').Where(c=>c!='o').Where(c=>c!='u');

foreach(char c in query) Console.Write(c);

在这个例子中,每一行附加到它上面分配的查询。所以显然所有的查询都会执行。

【讨论】:

  • 是的,我发现了一些东西。当函数返回 IEnumerable 程序时,它什么也不做。只是在某个地方记得它被称为。只有当 foreach 开始(要求枚举器)时,函数才会被执行。我说的对吗?
  • 是的,没错。它被称为deferred execution。如果您想立即执行,只需调用ToList(),LINQ 将立即执行并将所有内容放入 List 数据结构中。
  • 是的,没错……延迟执行。现在我清除了!谢谢
猜你喜欢
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 2011-03-06
  • 2021-12-25
  • 2013-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多