0

後続の 2 つのFROM句は、への呼び出しに変換されSelectManyます。

a)

var query = from c_1 in collection_1
            from c_2  in collection_2 
            from c_3 in collection_3
            select ...

間違っている場合は訂正してください。ただし、クエリ式は意味的に次のコードに変換されると思います。

collection_1.SelectMany(c_1 => c_1.collection_2.
               SelectMany(c_2 => c_2.collection_3.
                     Select(c_3 =>  ... )));

from c_3 in collection 常に範囲変数に「バインド」されていますか? 「バインドc_2」という用語を使用して、要素ごとに全体が列挙されるかどうかを尋ねていますか?collection_3c_2

b) a ) の下で私が正しいと仮定すると、それに最も近い定義された範囲変数に常に「バインド」されますc_3?

c) b)に対する答えが true の場合、次の例では偶数にc_3バインドされます。c_2

var query = from c_1 in collection_1
            from c_2  in collection_2 
            where ...
            from c_3 in collection_3

d) 次のクエリc_3にバインドされていますa(つまりa、全体groupAandBが列挙されます):

var query_1 =  from a in groupA
               join b in groupB on a equals b
                  into groupAandB
               from c_3 in groupAandB
               select c_3;

e) ここで、 d)に対する答えは実際に にバインドされていると仮定していc_3ますa。しかし、query_1コンパイル時に変換されるコードを見ると、c_3実際には匿名型a_1(つまりnew { a, groupAandB = os })にバインドされていると主張できます。

groupA.GroupJoin(groupB, a => a, b => b, (a, os) => new { a, groupAandB = os } ).
             SelectMany(a_1 => a_1.groupAandB );

f) 何が翻訳されるかを頭に入れておくと、d)query_1の下で行った仮定はおそらく概念的には正しいが、技術的には間違っていると主張できませんか?コンパイル時には変数がないか、おそらくどこかに定義されているからです。ボンネットの下ですが、実際には匿名型にバインドされており、 ?にはバインドされていません。c_3c_3a

編集:

1)

Join を使用すると、「2 番目の」コレクションは、最初のコレクションから現在「見ている」値に依存できなくなります。

a)の現在の値によって返されるcustomersコレクション (つまり) に参加できないことを本質的に意味していると思います。c.Ordersc

var query1 = from c in customers
             join o in c.Orders on c.CustomerId equals o.OrderID // this won't work
             select new { c.Name, o.OrderID, o.OrderDate };

b) ところで、なぜそのような結合が許可されないのですか (そのような結合を行うことは技術的に実行可能であると想定しています)、またはおそらく意味がないのはなぜですか?

2)

「C# 仕様は、関連する明示的な変換を提供します」

「明示的な変換が含まれる」とはどういう意味で、 e)f)の質問にどのように関係するのか詳しく説明していただけますか?

ありがとうございました

4

1 に答える 1

2

クエリaはコンパイルされます:

collection1
   .SelectMany(c1 => collection2, (c1, c2) => new { c1, c2 })
   .SelectMany(t0 => collection3, (t0, c2) => new { t0.c1, t0.c2, c3 })
;

collection2collection1;の要素ごとに列挙されます。collection3結果のアイテムのすべての組み合わせに対して列挙されます。

collection1を含む{ 1, 2 }、をcollection2含む{ 11, 12 }、およびをcollection3含む場合{ 21, 22 }、結果は次のようになります。

|----|----|----|
| c1 | c2 | c3 |
|----|----|----|
|  1 | 11 | 21 |
|  1 | 11 | 22 |
|  1 | 12 | 21 |
|  1 | 12 | 22 |
|  2 | 11 | 21 |
|  2 | 11 | 22 |
|  2 | 12 | 21 |
|  2 | 12 | 22 |
|----|----|----|

クエリcは次のようにコンパイルされます。

collection1
   .SelectMany(c1 => collection2, (c1, c2) => new { c1, c2 })
   .Where(t0 => ...)
   .SelectMany(t0 => collection3, (t0, c3) => new { t0.c1, t0.c2, c3 })
;

collection3フィルタを通過するcollection1アイテムのすべての組み合わせに対して列挙されます。collection2

クエリdの場合、それぞれがからの要素に一致するc_3アイテムのリストになるため、用語を正しく理解していれば、実際に「バインド」されます。groupBgroupAa

于 2012-10-24T18:16:38.340 に答える