2009-07-07 3 views
166

En utilisant les compilateurs C# caractéristiques de compréhension de requête, vous pouvez écrire du code comme:code équivalent au mot-clé « let » dans la méthode d'extension LINQ enchaîné appelle

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; 

Dans l'expression de requête ci-dessus, le mot-clé let permet une valeur à transmettre aux opérations where et orderby sans appels en double à animalName.Length.

Quel est l'ensemble équivalent d'appels de méthode d'extension LINQ qui réalise ce que le mot clé "let" fait ici?

+11

FYI, la spécification C# 3.0 explique chaque règle de traduction de la requête dans des détails atroces. –

+16

et pour ceux qui trouvent la spécification lourde, C# in Depth de Jon Skeet le couvre aussi ;-p –

+4

Je l'aime quand je suis tout comme "je me demande comment le mot-clé" let "correspond aux méthodes d'extension ... Je vais google, mais je doute que ma recherche trouve autre chose que de la camelote ... SO FTW! " – Will

Répondre

212

Soit n'a pas son propre fonctionnement; il piggy-backs de Select. Vous pouvez le voir si vous utilisez "réflecteur" pour séparer une DLL existante.

il sera quelque chose comme:

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, je ne savais pas que vous pouviez autoencapsuler en utilisant le nouvel opérateur comme ça. –

+17

Vous pouvez également utiliser le petit bouton "lambda" dans le panneau des résultats de LinqPad pour voir le code généré * si * vous commencez par un "Queryable".En d'autres termes, si vous changez votre première ligne en var names = new string [] {"Dog", ...} .AsQueryable(); Ensuite, lancez le tout dans LinqPad, cliquez sur le petit bouton lambda, vous verrez le code généré pratiquement identique à la réponse de Marc. –

+1

J'avais besoin d'utiliser la méthode d'extension '.Dump()' dans LinqPad pour voir le lambda résultant. – justanotherdev

77

Il y a un bon article here

Essentiellement let crée un tuple anonyme. C'est équivalent à:

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

On dirait que le blog a disparu –

+2

Plus maintenant, maintenant le lien vers l'archive web. – Ziv

+0

Je cite l'article ci-dessus «il semble prudent de ne pas utiliser le mot-clé let dans les cas où vous n'avez pas besoin de transformer une variable» –

5

Il y a aussi une méthode d'extension en System.Interactive Soient, mais son but est d'introduire une expression lambda à évaluer « en ligne » dans une expression fluide. Par exemple, considérons (en LINQPad, par exemple) l'expression suivante qui crée de nouveaux nombres aléatoires à chaque fois qu'il est exécuté:

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

Pour voir que de nouveaux échantillons aléatoires apparaissent à chaque fois, considérer les points suivants

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

qui produit des paires dans lesquelles la gauche et la droite sont différentes. Pour produire des paires dans lesquelles la gauche et à droite sont toujours les mêmes, faire quelque chose comme ce qui suit:

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

Si on pouvait invoquer des expressions lambda directement, nous pourrions écrire

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

Mais nous ne pouvons pas invoque des expressions lambda comme si elles étaient des méthodes.

Questions connexes