2008-11-18 8 views

Respuesta

127

Respuesta corta: no.

Respuesta larga que puede no ser relevante:

  • Si asigna el lambda a un tipo de delegado (como Func o Action) obtendrá un delegado anónimo.
  • Si asigna la lambda a un tipo de Expresión, obtendrá un árbol de expresiones en lugar de un delegado anónimo. El árbol de expresiones se puede compilar a un delegado anónimo.

Editar: Aquí hay algunos enlaces para Expressions.

  • System.Linq.Expression.Expression(TDelegate) (comenzar aquí).
  • Linq en memoria con delegados (como System.Func) utiliza System.Linq.Enumerable. Linq a SQL (y cualquier otra cosa) con expresiones usa System.Linq.Queryable. Verifique los parámetros en esos métodos.
  • Un Explanation from ScottGu. En pocas palabras, Linq in-memory producirá algunos métodos anónimos para resolver su consulta. Linq to SQL producirá un árbol de expresiones que representa la consulta y luego traducirá ese árbol a T-SQL. Linq to Entities producirá un árbol de expresiones que representa la consulta y luego traducirá ese árbol en SQL apropiado para la plataforma.
+2

Un tipo de expresión? Esto me parece un territorio nuevo. ¿Dónde puedo obtener más información sobre los tipos de Expresión y el uso de árboles de expresiones en C#? – MojoFilter

+0

Respuesta actualizada para explicar. –

+2

Respuesta aún más larga: hay motivos complicados por los que también son convertibles a diferentes tipos de delegados :) –

2

En los dos ejemplos anteriores no hay diferencia, cero.

La expresión:

() => { x = 0 } 

es una expresión Lambda con el cuerpo de la declaración, por lo que no puede ser compilado como un árbol de expresión. De hecho, ni siquiera compila porque necesita un punto y coma después de 0:

() => { x = 0; } // Lambda statement body 
() => x = 0  // Lambda expression body, could be an expression tree. 
+5

Seguramente eso significa que hay una diferencia de "uno compilará, el otro no";) –

2

David B es correcto. Tenga en cuenta que puede haber ventajas al usar árboles de expresiones. LINQ to SQL examinará el árbol de expresiones y lo convertirá en SQL.

También puede jugar trucos con lamdas y árboles de expresiones para pasar efectivamente los nombres de los miembros de la clase a un marco de trabajo en una forma segura de refactorización. Moq es un ejemplo de esto.

112

Me gusta la respuesta de David, pero pensé que sería pedante. La pregunta dice "Una vez que se compila", lo que sugiere que ambas expresiones tienen compiladas. ¿Cómo podrían ambos compilar, pero convirtiendo uno en un delegado y uno en un árbol de expresiones? Es complicado: tienes que usar otra característica de los métodos anónimos; el único que no es compartido por expresiones lambda. Si especifica un método anónimo sin especificar una lista de parámetros en total, es compatible con cualquier tipo de delegado que devuelva vacío y sin ningún parámetro out.Armados con este conocimiento, deberíamos poder construir dos sobrecargas para hacer que las expresiones sean completamente inequívocas pero muy diferentes.

¡Pero el desastre golpea! Al menos con C# 3.0, no puede convertir una expresión lambda con un cuerpo de bloque en una expresión, ni puede convertir una expresión lambda con una asignación en el cuerpo (incluso si se usa como valor de retorno). Esto puede cambiar con C# 4.0 y .NET 4.0, que permiten que se expresen más en un árbol de expresiones. En otras palabras, con los ejemplos que dio MojoFilter, los dos casi se convertirán siempre en lo mismo. (Más detalles en un minuto.)

Podemos utilizar el truco parámetros de delegado si cambiamos los cuerpos un poco sin embargo:

using System; 
using System.Linq.Expressions; 

public class Test 
{ 
    static void Main() 
    { 
     int x = 0; 
     Foo(() => x); 
     Foo(delegate { return x; }); 
    } 

    static void Foo(Func<int, int> action) 
    { 
     Console.WriteLine("I suspect the anonymous method..."); 
    } 

    static void Foo(Expression<Func<int>> func) 
    { 
     Console.WriteLine("I suspect the lambda expression..."); 
    } 
} 

pero espera! Podemos diferenciar entre los dos incluso sin usar árboles de expresión, si somos lo suficientemente astutos. El siguiente ejemplo usa las reglas de resolución de sobrecarga (y el truco de combinación de delegados anónimo) ...

using System; 
using System.Linq.Expressions; 

public class Base 
{ 
    public void Foo(Action action) 
    { 
     Console.WriteLine("I suspect the lambda expression..."); 
    } 
} 

public class Derived : Base 
{ 
    public void Foo(Action<int> action) 
    { 
     Console.WriteLine("I suspect the anonymous method..."); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     Derived d = new Derived(); 
     int x = 0; 
     d.Foo(() => { x = 0; }); 
     d.Foo(delegate { x = 0; }); 
    } 
} 

Ouch. Recuerde niños, cada vez que sobrecarga un método heredado de una clase base, un pequeño gatito comienza a llorar.

+6

Saqué mis palomitas y leí todo. Esa es una distinción en la que probablemente nunca pensaría aunque lo estuviera mirando directamente a la cara. – MojoFilter

+0

De acuerdo, quitando el trocito quejumbroso al final como claramente algunas personas * lo han * leído :) –

+21

Sabía algo de esto, pero debo felicitarlo por su habilidad para comunicárselo a los humanos. –

-1

Hay una diferencia

Ejemplo:

var mytask = Task.Factory.StartNew(() => 
{ 
    Thread.Sleep(5000); 
    return 2712; 
}); 
mytask.ContinueWith(delegate 
{ 
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture)); 
}); 

Y reemplazar con lambda: (error)

var mytask = Task.Factory.StartNew(() => 
{ 
    Thread.Sleep(5000); 
    return 2712; 
}); 
mytask.ContinueWith(()=> 
{ 
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture)); 
}); 
+9

¿Qué error? Pls menciona detalles. – nawfal

+0

Wrong ~ lambda falló solo porque la firma del parámetro del método no coincide. –

Cuestiones relacionadas