Una vez que se compila, ¿hay alguna diferencia entre:
delegate { x = 0; }
y
() => { x = 0 }
?
Una vez que se compila, ¿hay alguna diferencia entre:
delegate { x = 0; }
y
() => { x = 0 }
?
Respuestas:
Respuesta corta: no.
Respuesta más larga que puede no ser relevante:
Func
oAction
), obtendrá un delegado anónimo.Editar: Aquí hay algunos enlaces para Expresiones.
Me gusta la respuesta de Amy, pero pensé que sería pedante. La pregunta dice: "Una vez que se compila", lo que sugiere que ambas expresiones se han compilado. ¿Cómo podrían ambos compilar, pero con uno convertido en un delegado y otro en un árbol de expresión? Es complicado: debe usar otra característica de los métodos anónimos; el único que no es compartido por las expresiones lambda. Si especifica un método anónimo sin especificar una lista de parámetros en absoluto de que es compatible con cualquier tipo de delegado de regresar nula y sin ningúnout
parámetros. Armados con este conocimiento, deberíamos poder construir dos sobrecargas para que las expresiones sean completamente inequívocas pero muy diferentes.
¡Pero ocurre un desastre! 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, lo que permite que se exprese más en un árbol de expresión. En otras palabras, con los ejemplos que MojoFilter dio, los dos casi siempre se convertirán en lo mismo. (Más detalles en un minuto).
Sin embargo, podemos usar el truco de los parámetros de delegado si cambiamos un poco los cuerpos:
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 utiliza las reglas de resolución de sobrecarga (y el truco de coincidencia de delegado 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; } );
}
}
Ay. Recuerde niños, cada vez que sobrecarga un método heredado de una clase base, un gatito comienza a llorar.
delegate { ... }
es lo mismo que delegate() { ... }
: este último solo es compatible con un tipo de delegado sin parámetros.
En los dos ejemplos anteriores no hay diferencia, cero.
La expresion:
() => { x = 0 }
es una expresión Lambda con cuerpo de declaración, por lo que no se puede compilar como un árbol de expresión De hecho, ni siquiera se 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.
Amy B tiene razón. Tenga en cuenta que puede haber ventajas al usar árboles de expresión. LINQ to SQL examinará el árbol de expresión y lo convertirá a 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 una manera segura de refactorización. Moq es un ejemplo de esto.
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 conceptos básicos aquí.
Este es un método anónimo.
(string testString) => { Console.WriteLine(testString); };
Como los métodos anónimos no tienen nombres, 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. Por lo general, necesitamos un delegado para usarlos
s => s.Age > someValue && s.Age < someValue // will return true/false
Podemos usar un delegado func para usar esta expresión.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);