2010-06-09 9 views
26

Entiendo que cuando el compilador de C# ve un linq query comprehension, básicamente hace una traducción directa a los métodos de extensión Linq correspondientes y lambdas. es decir,linq "let" translation

from x in list 
select x.property 

se traduce a:

list.Select(x => x.property) 

mi pregunta es: ¿qué let cláusulas se traducen a. por ejemplo, cómo sería traducido esto por el compilador.

from x in list 
let v = SomeComplexExpressionDependingOnx 
select v 

(P. S. sé que esto podría reducirse a solo select SomeComplexExpressionDependingOnx pero quiero saber cómo se hace esto en general)

Gracias!

+1

+1 como no había usado antes. Informativo. – Kelsey

Respuesta

33

En este caso particular, se traduce a:

list.Select(x => SomeComplexExpressionDependingOnx); 

Pero puede haber un caso más complejo, como por ejemplo:

from x in list 
let v = SomeComplexExpressionDependingOnx 
where v > 10 && v+5 < 50 && SomeFunc(v) == "str" 
select x 

se traducirá en:

list.Where(x => 
    { 
     var v = SomeComplexExpressionDependingOnx; 
     return v > 10 && v+5 < 50 && SomeFunc(v) == "str"; 
    } 
) 

En otras palabras, la palabra clave let es una forma de minimizar y/u optimizar su consulta. Es decir, sin la palabra clave let que tendría que escribir:

from x in list 
where 
    SomeComplexExpressionDependingOnx > 10 && 
    SomeComplexExpressionDependingOnx+5 < 50 && 
    SomFunc(SomeComplexExpressionDependingOnx) == "str" 
select x 

resultando en una posible evaluación de triple de la misma expresión.

Actualización, a raíz de una pregunta en el comentario.

Primero, ¿qué tiene de atemorizante "expresiones de bloque"? Son solo una abreviatura de delegado arbitrario. Es decir, la siguiente expresión:

Func<string,int> f = 
    s => 
    { 
     var ln = s.Length; 
     return ln/2; 
    } 

es equivalente a lo siguiente:

int CompilerGeneratedMethodIdentifier0(string s) 
{ 
    var ln = s.Length; 
    return ln/2; 
} 

... 

Func<string, int> f = new Func<string, int>(CompilerGeneratedMethodIdentifier0); 

Segunda, lo que es tan especial sobre las expresiones "bloquear"? ¿Sabías que mmm ...llamémosles "sin bloque" ¿las expresiones también se expanden al mismo código? Es decir, el código simple new Func<string,int>(s => s.Length/2) es equivalente a absoluta:

int CompilerGeneratedMethodIdentifier0(string s) 
{ 
    return s.Length/2; 
} 

... 

new Func<string, int>(CompilerGeneratedMethodIdentifier0); 

Tercer, lo que es tan no linqy sobre las expresiones "bloquear"? LINQ usa delegados por todas partes, y realmente no le importa a LINQ qué atajo exacto utilizas para representar a esos delegados.

En particular, su expresión from a in list where a.SomeProp > 10 select new { A = a, B = a.GetB() } se traduce en lo siguiente:

class AnonymousType0 
{ 
    public MyClass A { get; set; } 
    public othertype B { get; set; } 
} 

bool WhereFunc0(MyClass a) 
{ 
    return a.SomeProp > 10; 
} 

AnonymousType0 SelectResultFunc0(MyClass a) 
{ 
    AnonymousType0 result = new AnonymousType0(); 
    result.A = a; 
    result.B = a.GetB(); 
    return result; 
} 

... 

list 
    .Where(new Func<MyClass,bool>(WhereFunc0)) 
    .Select(new Func<MyClass,AnonymousType0>(SelectResultFunc0)); 

Cuarta, para obtener la comprensión de esta manera, uno puede jugar con el lenguaje y pensar. Usa tu cerebro, eso es.

Y quinto, si el consejo anterior no funciona para usted por una razón u otra, siempre tiene ILSpy. Herramienta muy útil, todo el mundo debería tener una.

+0

eh, nunca hubiera esperado que se resolviera en una expresión de bloque, las expresiones de bloque simplemente no me parecen muy lindas. ¿Tiene una fuente para esto, o es solo una suposición? – luke

+0

He actualizado la respuesta para dirigir su comentario. –

+0

gracias por el arduo trabajo, supongo que cuando dije que no pensaba que las expresiones de bloques fueran muy "complicadas", fue porque asociaba (incorrectamente) expresiones de bloques con expresiones que causaban efectos secundarios (que definitivamente no es linq'y), pero claramente estaba equivocado :). Gracias de nuevo – luke

0

Sólo una conjetura ya que rara vez usar la sintaxis de consulta:

list.Select(x => new { v = SomeComplexExpressionDependingOnx(x) }); 

El let es simplemente la asignación de una nueva var v el Select es devolverlo.

También podría ser el siguiente si no desea que un objeto anon con v en ella:

var v = list.Select(x => SomeComplexExpressionDependingOnx(x)); 
+2

Wow votos negativos para dar una explicación? Al menos postear por qué o por qué votar no ayuda a informarme de lo que podría hacer de manera diferente. – Kelsey

+0

Supongo que está mal. El código del OP no creará un tipo anónimo. –

+0

@Matthew Flaschen interesante, si no es así, ¿cómo es 'select v' válido? no está 'v' almacenando el resultado de' SomeComplexExpressionDependingOnx'? No lo he usado nunca antes, así que podría haber sido una mala suposición, pero me interesó saber por qué ahora me gusta OP. Supongo que no es anónimo porque 'SomeComplexExpressionDependingOnx' devolvería un tipo conocido? – Kelsey

-1
list.Select(x => SomeComplexExpressionDependingOnx); 

En general, let básicamente funciona como una variable readonly la celebración de un rango.

8

Eche un vistazo a LINQPad, puede escribir la consulta y presionar el símbolo lamba para ver cómo se verá la salida. Por ejemplo Tomé esta consulta:

var names = new[] { "Tom", "Dick", "Harry", "Mary", "Jay" }.AsQueryable(); 

var results = 
    from n in names 
    let n1 = String.IsNullOrEmpty(n) 
    select n1; 

results.Dump(); 

Y salida de los siguientes:

System.String[] 
    .Select (
     n => 
     new 
     { 
      n = n, 
      n1 = String.IsNullOrEmpty (n) 
     } 
    ) 
    .Select (temp0 => temp0.n1) 

Por lo tanto, sí que parece que la let se traduce en un valor de temperatura tan anónimo, y luego se consume en el exterior Seleccionar instrucción.

Me encanta LINQPad por la capacidad de escribir la consulta y ver cómo se traduciría.

+0

Pensé que tenía que haber un tipo anónimo o en otro sitio donde se guardaría el v temporalmente ... – Kelsey

Cuestiones relacionadas