2009-07-07 3 views
166

die # Compiler Abfrage-Funktionen C verwenden, können Sie Code wie schreiben:-Code entspricht das Verfahren ‚lassen‘ Schlüsselwort in gekettet LINQ Erweiterung ruft

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; 

In dem Abfrageausdruck oben, das let Schlüsselwort ermöglicht einen Wert an die Where- und Orderby-Operationen ohne doppelte Aufrufe an animalName.Length weitergeleitet werden.

Was ist das Äquivalent Satz von LINQ-Extension-Methode aufruft, das erreicht, was die „let“ Stichwort hier tut?

+11

FYI, die C# 3.0-Spezifikation erklärt in allen Einzelheiten jede Abfrage-Übersetzungsregel. –

+16

und für diejenigen, die die Spezifikation schwer gehen, Jon Skeet C# in Depth finden deckt es zu ;-p –

+4

Ich liebe es, wenn ich alle wie „bin frage mich, wie die' let' Schlüsselwort Karten Erweiterungsmethoden ... Ich werde google es, aber ich bezweifle, dass meine Suche alles andere als Müll finden wird ... SO FTW! " – Will

Antwort

212

Lassen Sie uns nicht seine eigene Operation haben; es Piggy-Backs von Select. Sie können dies sehen, wenn Sie "Reflektor" verwenden, um eine vorhandene DLL auseinander zu ziehen.

es wird etwas wie:

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

Woah verwandeln müssen, ich wusste nicht, dass Sie den neuen Betreiber wie die Verwendung von autoencapsulate könnte. –

+17

Sie können auch die kleinen „Lambda“ im Ergebnisbereich des LinqPad verwenden Sie den generierten Code zu sehen * wenn * Sie mit einem Abfragbare starten.Mit anderen Worten, wenn Sie die erste Zeile in var names ändern = new string [] {"Dog", ...} .AsQueryable(); dann lasst das Ganze in LinqPad laufen, klickt auf den kleinen Lambda-Knopf, ihr werdet den generierten Code sehen, der mit Marc's Antwort praktisch identisch ist. –

+1

Ich musste die '.Dump()' Erweiterung Methode in LinqPad verwenden, um das resultierende Lambda zu sehen. – justanotherdev

77

Es ist ein guter Artikel here

Im Wesentlichen let ein anonymes Tupel erzeugt. Es entspricht:

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

Sieht so aus, als wäre der Blog verschwunden –

+2

Nicht mehr, jetzt verlinkt zum Webarchiv. – Ziv

+0

ich den Artikel zitieren oben 'es ratsam scheint gegen mit dem Schlüsselwort let in den Fällen zu empfehlen, wo Sie keine variable' –

5

Es gibt auch eine .let Erweiterungsmethode in System.Interactive, aber ihr Zweck ist es, einen Lambda-Ausdruck einzuführen ausgewertet werden 'in-line' in ein flüssiger Ausdruck. Betrachten wir zum Beispiel (in LinqPad, sagen) den folgenden Ausdruck, die jedes Mal neue Zufallszahlen erzeugt er ausgeführt hat:

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

auf die neue Stichproben jedes Mal auftauchen zu sehen, betrachten Sie das folgende

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

, die Paare erzeugt, in denen links und rechts unterschiedlich sind. Zur Herstellung von Paaren, bei denen die linke und rechte sind immer die gleichen, so etwas wie die folgenden:

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

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

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

schreiben Aber wir können nicht Rufen Sie Lambda-Ausdrücke auf, als wären sie Methoden.

Verwandte Themen