delegar palabra clave vs. notación lambda

Una vez que se comstack, ¿hay alguna diferencia entre:

delegate { x = 0; } 

y

 () => { x = 0 } 

?

Respuesta corta: no.

Una respuesta más 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 el 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 comstackr a un delegado anónimo.

Editar: Aquí hay algunos enlaces para Expressions.

  • System.Linq.Expression.Expression (TDelegate) (comienza aquí).
  • Linq in-memory con delegates (como System.Func) usa System.Linq.Enumerable . Linq to SQL (y cualquier otra cosa) con expresiones usa System.Linq.Queryable . Verifique los parámetros en esos métodos.
  • Una explicación de 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.

Me gusta la respuesta de David, pero pensé que sería pedante. La pregunta dice, “Una vez que se comstack”, lo que sugiere que ambas expresiones se han comstackdo. ¿Cómo podrían ambos comstackr, 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, es compatible con cualquier tipo de delegado que devuelva vacío y sin ningún parámetro de 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 siempre se convertirán en la misma cosa. (Más detalles en un minuto.)

Podemos usar el truco de parámetros delegates si cambiamos un poco los cuerpos un poco:

 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 action) { Console.WriteLine("I suspect the anonymous method..."); } static void Foo(Expression> 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 delegates 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 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; } ); } } 

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

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 expresión para pasar efectivamente los nombres de los miembros de la clase a un marco de trabajo en una forma de refactorización segura. Moq es un ejemplo de esto.

En los dos ejemplos anteriores, no hay diferencia, cero.

La expresion:

 () => { x = 0 } 

es una expresión Lambda con cuerpo de statement, por lo que no se puede comstackr como un árbol de expresiones. De hecho, ni siquiera comstack 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. 

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 lo reemplazo con lambda: (error)

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

Algunos básicos aquí.

Este es un método anónimo

 (string testString) => { Console.WriteLine(testString); }; 

Como el método anónimo no tiene ningún nombre, necesitamos un delegado en el que podamos asignar ambos métodos o expresiones. p.ej

 delegate void PrintTestString(string testString); // declare a delegate PrintTestString print = (string testString) => { Console.WriteLine(testString); }; print(); 

Lo mismo con la expresión lambda. Usualmente necesitamos delegar para usarlos

 s => s.Age > someValue && s.Age < someValue // will return true/false 

Podemos usar un delegado de func para usar esta expresión.

 Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ; bool result = checkStudentAge ( Student Object);