对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();
我是否可以期望count
等于2,如果我希望重用那个IEnumerable,我还能期望iEnum3
枚举"3", "4", "5", "6"
吗?
我正在尝试避免创建新数组,即使它们逻辑上更简单,因为初始数组已经相对较大(来自更大的文件流)。
答案 0 :(得分:3)
他们做&#34;堆叠&#34;就像你说的那样(通常称为&#34; chaining&#34;)。
那些LINQ语句(Take,Skip)是IEnumerable的扩展,最终结果是iEnum4
是exampleArray.Skip(1).Take(5).Skip(1).Take(2)
该语句的最终评估将推迟到调用某些方法(例如Count
),此时将评估LINQ语句并将最终结果存储在int count
变量中。< / p>
我可以期望数量等于2,我还能指望iEnum3枚举超过&#34; 3&#34;,&#34; 4&#34;,&#34; 5&#34;,&#34; 6&#34;如果我想重用那个IEnumerable?
是的,iEnum3
会评估其中包含的任何LINQ查询,以便iEnum3.Count()
可以评估为与iEnum4.Count()
不同的值。但是,如果您在程序中三次调用iEnum3.Count()
,则可能会得到三种不同的结果,因为评估会延迟,exampleArray
中的值可能会在此期间发生变化。
答案 1 :(得分: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。这意味着在迭代结果集之前,它们实际上不会被评估。如果您检查了结果集,上面的注释只表明变量将是什么,但Linq实际 你打电话给Count
)。因此,虽然您可以在其他Linq查询中重用iEnum3
,但它可能不会有任何性能优势 - 尽管它可能会提升代码重用/可读性。