2009-07-07 18 views
166

Uso de las funciones de comprensión de C# compiladores consulta, puede escribir código como:Código equivalente a la palabra clave 'dejar' en el método de extensión LINQ encadenado llama

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; 

En la expresión de consulta más arriba, la palabra clave let permite un valor para pasar a las operaciones where y orderby sin llamadas duplicadas a animalName.Length.

¿Cuál es el conjunto equivalente de llamadas al método de extensión LINQ que logra lo que la palabra clave "let" hace aquí?

+11

FYI, la especificación C# 3.0 explica cada regla de traducción de comprensión de consulta en detalles insoportables. –

+16

y para aquellos que encuentran que las especificaciones son complicadas, la C# en profundidad de Jon Skeet también lo cubre ;-p –

+4

Me encanta cuando me pregunto "cómo se asocian los mapas de palabra clave' let' a los métodos de extensión ... Lo haré googlealo, pero dudo que mi búsqueda encuentre nada más que basura ... ¡ASÍ QUE! " – Will

Respuesta

212

Let no tiene su propia operación; se retrae de Select. Puedes ver esto si usas "reflector" para separar una dll existente.

será algo así como:

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, no sabía que podía autoencapsularse con el nuevo operador de esa manera. –

+17

También puede usar el pequeño botón "lambda" en el panel de resultados de LinqPad para ver el código generado * si * comienza con un Queryable.En otras palabras, si cambia su primera línea a var names = new string [] {"Dog", ...} .AsQueryable(); luego ejecute todo en LinqPad, haga clic en el pequeño botón lambda, verá código generado prácticamente idéntico a la respuesta de Marc. –

+1

Necesitaba usar el método de extensión '.Dump()' en LinqPad para ver el lambda resultante. – justanotherdev

77

Hay un buen artículo here

Esencialmente let crea una tupla en el anonimato. Es equivalente a:

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

Parece que el blog desapareció –

+2

Ya no existe, ahora vinculando al archivo web. – Ziv

+0

Cito el artículo anterior 'parece prudente recomendar no utilizar la palabra clave let en los casos en que no es necesario transformar una variable' –

5

También hay un método de extensión ¡Deje en System.Interactive, pero su propósito es introducir una expresión lambda para ser evaluados 'en línea' en una expresión fluida. Por ejemplo, considere (en LINQPad, por ejemplo) la siguiente expresión que crea nuevos números aleatorios cada vez que se ejecuta:

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

ver que nuevas muestras aleatorias aparecen cada vez, considere lo siguiente

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

que produce pares en los que la izquierda y la derecha son diferentes. Para producir pares en el que la izquierda y la derecha son siempre los mismos, hacer algo como lo siguiente:

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

Si pudiéramos invocar directamente las expresiones lambda, para escribir te

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

Pero no podemos invocar expresiones lambda como si fueran métodos.

Cuestiones relacionadas