LINQ延迟评估导致数组迭代器

时间:2015-09-01 20:49:08

标签: c# linq lazy-evaluation

我有一个包含四个EnumerableRowCollections的类,它们都指向同一个DataTable。主要的一个将需要在不同的类实例中过滤掉的其他三个的不同组合。由于其中三个是相关的,我把它们放在一个数组中。

EnumerableRowCollection<DataRow> valid;
EnumerableRowCollection<DataRow>[] pending;

所有这些集合都是在类构造函数中定义的,但是由于LINQ的惰性求值而在稍后进行评估。

我还有一系列布尔值,用于确定哪些&#34;待定&#34;集合被过滤掉了&#34;有效的&#34;采集。这些也在构造函数中分配,并且永远不会更改。

Boolean[] pendingIsValid;

&#34;有效&#34;集合过滤如下:

for (var i = 0; i < pending.Length; i++)
    if (pendingIsValid[i] && pending[i].Count() > 0)
        valid = valid.Where(r => !pending[i].Contains(r));

这也发生在构造函数中,但Where子句是按照预期延迟计算的。

这大部分时间都有效,但在少数情况下,当收集评估发生在路上时,我得到了一个奇怪的例外。

我得到一个IndexOutOfRange因为本地迭代器变量,我在上面的for循环中设置为3.

问题:

  1. 我可以制作&#34; Where&#34;非懒惰地评估数组索引器(或其他子表达式)?
  2. 迭代器如何增加到3?这种懒惰的评估是否计入&#34;重新进入&#34;循环?
  3. !?!?

2 个答案:

答案 0 :(得分:3)

将其更改为:

for (var i = 0; i < pending.Length; i++)
    if (pendingIsValid[i] && pending[i].Count() > 0) 
    {
        var j = i;
        valid = valid.Where(r => !pending[j].Contains(r));
    }

对于问题#1 - 你可以通过在末尾添加.ToList()来使它不是懒惰的。但是,通过上述修复,您可以保持懒惰。

请阅读:Captured variable in a loop in C#了解

答案 1 :(得分:0)

很好,Rob。我在等待回复的过程中也发现了这一点,但你的看起来更清洁。

for (var i = 0; i < pending.Length; i++) {
    var p = pending[i];
    if (pendingIsValid[i] && p.Count() > 0) 
        valid = valid.Where(r => !p.Contains(r));
}