0

在我的代码中,我有三个列表。

  1. 我已排队等待创建/检索的项目列表(请求)
  2. 我当前正在构建(工作)的项目列表
  3. 我上次请求中缺少的项目列表。这可能包括我已经请求并正在检索的项目的重复项。(失踪)

我只想为尚未排队请求或正在处理的项目排队请求,我想到了以下 LINQ 表达式......

// Queue object requests if they aren't already requested
foreach (int id in missing.Except(requested.Concat(working)))
    requested.Enqueue(id);

但是,这里出现了危险信号,假设 except 正在使用延迟执行,我可能在枚举列表时修改了列表,这通常会引发异常或导致问题。

当然,我可以在不使用 LINQ 的情况下重写它和/或单独检查每个列表,然后再添加,但问题仍然存在。为什么或为什么这不起作用?我认为它可能会抛出异常,所以我编写了以下测试:

private void Test()
    {
        Queue<int> missing   = new Queue<int>();
        Queue<int> requested = new Queue<int>();
        Queue<int> working   = new Queue<int>();

        missing.Enqueue(5);  // also in working
        missing.Enqueue(10);
        missing.Enqueue(67);
        missing.Enqueue(96); // also in requested

        requested.Enqueue(47);
        requested.Enqueue(66);
        requested.Enqueue(84);
        requested.Enqueue(89);
        requested.Enqueue(96);

        working.Enqueue(1);
        working.Enqueue(5);
        working.Enqueue(33);

        foreach (int i in missing.Except(requested.Concat(working)))
            requested.Enqueue(i);
    }

此代码有效并返回预期结果(请求现在包含 7 项,包括 10 和 67)。我认为这可能会引发异常。那么,我错了,这很好,还是我对,这会导致问题?

(显然问题不在于如何使其工作,因为我知道我可以先检查请求,但我想了解这个 LINQ 表达式的工作原理)

4

1 回答 1

2

由于将一个集合的所有元素与另一个集合进行比较的潜在 O(n^2) 除外,内部使用哈希集通过其哈希码对集合项目进行分区,然后仅比较每个桶中的项目。

这样做的结果是,除了实际上不是一个惰性 LINQ 运算符,而是在您读取第一项时对其进行完全评估。

于 2013-10-23T23:19:10.127 回答