【问题标题】:Can you stack multiple IEnumerable queries?您可以堆叠多个 IEnumerable 查询吗?
【发布时间】:2014-02-03 09:31:05
【问题描述】:

IEnumerable 对象上的 Linq 方法是堆栈还是覆盖以前的方法?

例如

string[] exampleArray = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
IEnumerable<string> iEnum1 = exampleArray.Skip(1); 
IEnumerable<string> iEnum2 = iEnum1.Take(5); 
IEnumerable<string> iEnum3 = iEnum2.Skip(1); 
IEnumerable<string> iEnum4 = iEnum3.Take(2); 
int count = iEnum4.Count(); 

如果我希望重用该 IEnumerable,我是否可以期望 count 等于 2,我是否仍然可以期望 iEnum3 枚举 "3", "4", "5", "6"

我试图避免创建新数组,即使它们在逻辑上更易于使用,因为初始数组已经相对较大(来自更大的文件流)。

【问题讨论】:

  • 您可能想查看调试器中的值或将它们打印到控制台。
  • 你可以这样写 exampleArray.Skip(1).Take(5).Skip(1).Take(2).Count();

标签: c# .net linq indexing ienumerable


【解决方案1】:

是的 count 等于 2。让我们分解一下:

var iEnum1 = exampleArray.Skip(1); // { "2", "3", "4", "5", "6", "7", "8", "9" }
var iEnum2 = iEnum1.Take(5);       // { "2", "3", "4", "5", "6" }
var iEnum3 = iEnum2.Skip(1);       // { "3", "4", "5", "6" }
var iEnum4 = iEnum3.Take(2);       // { "3", "4" }
int count = iEnum4.Count();        // 2

当然,您可以像这样将它们链接在一起:

int count = exampleArray.Skip(1).Take(5).Skip(1).Take(2).Count()

但是,需要注意的是,Linq 查询是lazy。这意味着在您遍历结果集之前,它们实际上不会被评估。如果您检查了结果集,上面的 cmets 仅指示变量 是什么,但 Linq 在需要它之前不会实际上 生成该结果(例如,当你打电话给Count)。因此,虽然您可以在其他 Linq 查询中重用 iEnum3,但它可能不会带来任何性能优势——尽管它可能会促进代码重用/可读性。

【讨论】:

  • 因此,如果您想缓存 iEnum3 且每次枚举时都没有性能命中,则必须在第 4 行之后使用 ToArray。
  • @csaam 您必须在第 3 行的 Skip 之后执行此操作。您也可以使用 ToList(速度稍快一些)。
  • 是的,我把我的变量混在了我的脑海里。我不知道 ToList 更快。对你有一个参考,我很好奇。
【解决方案2】:

它们按照您的说法“堆叠”(通常称为“链接”)。

那些 LINQ 语句(Take、Skip)是 IEnumerable 的扩展,最终结果将是 iEnum4exampleArray.Skip(1).Take(5).Skip(1).Take(2)

该语句的最终评估会延迟到调用某些方法(例如Count),此时会评估 LINQ 语句并将最终结果存储在您的 int count 变量中。

如果我希望重用该 IEnumerable,我是否可以期望 count 等于 2,并且我仍然可以期望 iEnum3 枚举“3”、“4”、“5”、“6”吗?

是的,iEnum3 将评估它包含的任何 LINQ 查询,这样iEnum3.Count() 可以评估为与iEnum4.Count() 不同的值。但是,如果您在程序中调用 iEnum3.Count() 三个不同的时间,您可能会得到三个不同的结果,因为评估被推迟,同时exampleArray 中的值可能已经改变。

【讨论】:

  • iEnum3.Count 只有在 exampleArray 是可以正确更改的类型集合时才会更改?由于exampleArrayArray 并且Array 初始化后无法更改其大小?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多