連鎖LINQ拡張メソッド呼び出しの 'let'キーワードに相当するコード


191

C#コンパイラのクエリ理解機能を使用すると、次のようなコードを記述できます。

var names = new string[] { "Dog", "Cat", "Giraffe", "Monkey", "Tortoise" };
var result =
    from animalName in names
    let nameLength = animalName.Length
    where nameLength > 3
    orderby nameLength
    select animalName; 

上記のクエリ式では、letキーワードにより、への重複した呼び出しなしに、whereおよびorderby操作に値を転送できますanimalName.Length

ここで「let」キーワードの機能を実現するLINQ拡張メソッド呼び出しの同等のセットは何ですか?


11
ちなみに、C#3.0仕様では、すべてのクエリ内包変換ルールが非常に詳細に説明されています。
Eric Lippert、

17
そして、スペックが重くなっているのを見つけた人のために、DonthのJon SkeetのC#もそれをカバーしています;-p
Marc Gravell

C#言語仕様はダウンロード可能なWordドキュメントであり、そのコンテンツは検索エンジンによって索引付けされておらず、リンクもオンラインでの閲覧もできません。仕様がオンラインで入手できれば、非常に役立ちます。
Olivier Jacot-Descombes

回答:


249

独自の操作はありません。それはピギーバックしSelectます。これは、「リフレクター」を使用して既存のdllを分離する場合に確認できます。

それは次のようなものになります:

var result = names
        .Select(animalName => new { nameLength = animalName.Length, animalName})
        .Where(x=>x.nameLength > 3)
        .OrderBy(x=>x.nameLength)
        .Select(x=>x.animalName);

4
ああ、私はあなたがそのような新しい演算子を使用して自動カプセル化できることを知りませんでした。
David Pfeffer

19
また、LinqPadの結果ペインにある小さな「lambda」ボタンを使用して、Queryableで開始した場合に生成されたコードを表示することもできます。つまり、最初の行をvar names = new string [] {"Dog"、...} .AsQueryable();に変更すると、次に、すべてをLinqPadで実行し、小さなラムダボタンをクリックすると、Marcの答えと実質的に同じ生成コードが表示されます。
Reb.Cabin '30

3
.Dump()結果のラムダを表示するには、LinqPad の拡張メソッドを使用する必要がありました。
justanotherdev 2015

88

ここに良い記事があります

基本的にlet、匿名のタプルを作成します。これは次と同等です。

var result = names.Select(
  animal => new { animal = animal, nameLength = animal.Length })
.Where(x => x.nameLength > 3)
.OrderBy(y => y.nameLength)
.Select(z => z.animal);

上記の記事を引用しますit seems prudent to recommend against using the let keyword in cases where you do not need to transform a variable
JB。モニカと。

さらに引用しますThis could be considered a micro-optimisation
Monsignor

7

System.Interactiveには.Let拡張メソッドもありますが、その目的は、滑らかな式で「インライン」で評価されるラムダ式を導入することです。たとえば、(LinqPadで)実行されるたびに新しい乱数を作成する次の式について考えてみます。

var seq = EnumerableEx.Generate(
    new Random(),
    _ => true,
    _ => _,
    x => x.Next());

毎回新しいランダムサンプルが表示されることを確認するには、次のことを考慮してください。

seq.Zip(seq, Tuple.Create).Take(3).Dump();

これは、左と右が異なるペアを生成します。左と右が常に同じであるペアを生成するには、次のようにします。

seq.Take(3).ToList().Let(xs => xs.Zip(xs, Tuple.Create)).Dump(); 

ラムダ式を直接呼び出すことができれば、次のように書くことができます。

(xs => xs.Zip(xs, Tuple.Create))(seq.Take(3).ToList()).Dump();

しかし、ラムダ式をメソッドのように呼び出すことはできません。


1

チェーンされたLINQ拡張メソッド呼び出しの 'let'キーワードに相当するコードについて

上記のコメントは無効です

var x = new List<int> { 2, 3, 4, 5, 6 }.AsQueryable();
(from val in x
let val1 = val
let val2 = val + 1
where val2 > val1
select val
).Dump();

作り出す

System.Collections.Generic.List`1[System.Int32]
.Select(
  val =>
     new
     {
         val = val,
         val1 = val
     }
)
.Select(
  temp0 =>
     new
     {
         temp0 = temp0,
         val2 = (temp0.val + 1)
     }
)
.Where(temp1 => (temp1.val2 > temp1.temp0.val1))
.Select(temp1 => temp1.temp0.val)

複数letが最適化されました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.