wake-up-neo.net

Code, der dem Schlüsselwort 'let' in verketteten LINQ-Erweiterungsmethodenaufrufen entspricht

Mit den Funktionen zum Verständnis von C # -Compilern können Sie folgenden Code schreiben:

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; 

Im obigen Abfrageausdruck ermöglicht das Schlüsselwort let, dass ein Wert an die where- und orderby-Operationen weitergeleitet wird, ohne dass doppelte Aufrufe von animalName.Length.

Was ist der äquivalente Satz von LINQ-Erweiterungsmethodenaufrufen, der das bewirkt, was das Schlüsselwort "let" hier bewirkt?

184
LBushkin

Let hat keine eigene Operation; es huckepack von Select. Sie können dies sehen, wenn Sie "Reflektor" verwenden, um eine vorhandene DLL auseinander zu ziehen.

es wird etwas sein wie:

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

Es gibt einen guten Artikel hier

Im Wesentlichen erstellt let ein anonymes Tupel. Es ist äquivalent zu:

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

Es gibt auch eine .Let-Erweiterungsmethode in System.Interactive, deren Zweck jedoch darin besteht, einen Lambda-Ausdruck einzuführen, der in einem fließenden Ausdruck 'in-line' ausgewertet werden soll. Betrachten Sie beispielsweise (in LinqPad) den folgenden Ausdruck, der bei jeder Ausführung neue Zufallszahlen erzeugt:

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

Beachten Sie Folgendes, um zu sehen, dass jedes Mal neue Zufallsstichproben angezeigt werden

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

das erzeugt Paare, in denen links und rechts unterschiedlich sind. Gehen Sie wie folgt vor, um Paare zu erstellen, bei denen links und rechts immer gleich sind:

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

Wenn wir Lambda-Ausdrücke direkt aufrufen könnten, könnten wir schreiben

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

Aber wir können Lambda-Ausdrücke nicht so aufrufen, als wären sie Methoden.

6
Reb.Cabin

about Code, der dem Schlüsselwort 'let' in verketteten LINQ-Erweiterungsmethodenaufrufen entspricht

der obige Kommentar ist nicht mehr gültig

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

produziert

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)

so werden jetzt mehrere let optimiert

0
Fabio Angela