LINQ 惰性求值导致数组迭代器出现问题

LINQ lazy evaluation causing issues with array iterator

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

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

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

我还有一个布尔数组,用来判断哪些"pending"集合被过滤掉了"valid"集合。这些也在构造函数中分配,并且永远不会改变。

Boolean[] pendingIsValid;

"valid" 集合是这样过滤的:

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,因为本地迭代器变量 i 在我上面的 for 循环中设置为 3。


问题:

  1. 我可以让 "Where" 非惰性地评估数组索引器(或其他子表达式)吗?
  2. 迭代器是如何递增到 3 的?这个惰性求值算作 "re-entering" 循环吗?
  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# 解释

太棒了,罗布。我在等待回复时也想出了这个,但你的看起来更干净了。

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));
}