0

私のコードには、3 つのリストがあります。

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

このコードは機能し、期待される結果を返します (現在、要求されたアイテムには 10 と 67 を含む 7 つのアイテムが含まれています)。私はそれが例外をスローするかもしれないと思った..だから、私は間違っていたのですか、これは問題ありませんか、それともこれが問題を引き起こすのは正しいですか?

(明らかに、問題はそれを機能させる方法ではありません。最初に要求されたものを確認するだけでよいことはわかっていますが、このLINQ式の仕組みを理解したかったのです)

4

1 に答える 1

2

あるセットのすべての要素を別のセットと比較すると O(n^2) になる可能性があるため、Except はハッシュ セットを内部的に使用して、ハッシュ コードを介してコレクション アイテムを分割し、各バケット内のアイテムのみを比較します。

この結果、Except は実際には遅延 LINQ 演算子ではなく、最初の項目を読み取るときに完全に評価されます。

于 2013-10-23T23:19:10.127 に答える