tutorial expresiones curso c# c#-3.0 lambda

curso - C#expresiones Lambda: ¿Por qué debo usarlas?



linq c# (14)

Es una forma de tomar una pequeña operación y colocarla muy cerca de donde se usa (no a diferencia de declarar una variable cerca de su punto de uso). Se supone que esto hace que tu código sea más legible. Al anonimizar la expresión, también es mucho más difícil que alguien rompa el código de su cliente si la función se usa en otro lugar y se modifica para "mejorarla".

Del mismo modo, ¿por qué necesitas usar foreach? Puede hacer todo en foreach con un simple for loop o simplemente usando IEnumerable directamente. Respuesta: no lo necesita , pero hace que su código sea más legible.

He leído rápidamente la documentación de Microsoft Lambda Expression .

Este tipo de ejemplo me ha ayudado a entender mejor, sin embargo:

delegate int del(int i); del myDelegate = x => x * x; int j = myDelegate(5); //j = 25

Sin embargo, no entiendo por qué es una innovación. Es solo un método que muere cuando la "variable de método" termina, ¿verdad? ¿Por qué debería usar esto en lugar de un método real?


Esta es quizás la mejor explicación de por qué usar expresiones lambda -> https://youtu.be/j9nj5dTo54Q

En resumen, se trata de mejorar la legibilidad del código, reducir las posibilidades de errores al reutilizar en lugar de replicar el código y aprovechar la optimización que se produce entre bastidores.


Esta es solo una forma de usar una expresión lambda. Puede usar una expresión lambda en cualquier lugar donde pueda usar un delegado. Esto te permite hacer cosas como esta:

List<string> strings = new List<string>(); strings.Add("Good"); strings.Add("Morning") strings.Add("Starshine"); strings.Add("The"); strings.Add("Earth"); strings.Add("says"); strings.Add("hello"); strings.Find(s => s == "hello");

Este código buscará en la lista una entrada que coincida con la palabra "hola". La otra forma de hacer esto es pasar un delegado al método Buscar, de esta manera:

List<string> strings = new List<string>(); strings.Add("Good"); strings.Add("Morning") strings.Add("Starshine"); strings.Add("The"); strings.Add("Earth"); strings.Add("says"); strings.Add("hello"); private static bool FindHello(String s) { return s == "hello"; } strings.Find(FindHello);

EDITAR :

En C # 2.0, esto podría hacerse usando la sintaxis anónima de delegado:

strings.Find(delegate(String s) { return s == "hello"; });

Lambda ha limpiado significativamente esa sintaxis.


La expresión Lambda es una forma concisa de representar un método anónimo. Tanto los métodos anónimos como las expresiones Lambda le permiten definir la implementación del método en línea, sin embargo, un método anónimo requiere explícitamente que defina los tipos de parámetros y el tipo de retorno para un método. La expresión Lambda usa la característica de inferencia de tipo de C # 3.0 que le permite al compilador inferir el tipo de variable según el contexto. ¡Es muy conveniente porque nos ahorra mucho escribir!


La innovación está en el tipo seguridad y transparencia. Aunque no declara tipos de expresiones lambda, se deducen y pueden utilizarse para búsqueda de código, análisis estático, herramientas de refactorización y reflexión en tiempo de ejecución.

Por ejemplo, antes de que pudiera haber usado SQL y podría obtener un ataque de inyección de SQL, porque un hacker pasó una cadena donde normalmente se esperaba un número. Ahora usaría una expresión lambda LINQ, que está protegida de eso.

La construcción de una API LINQ en delegados puros no es posible, ya que requiere la combinación de árboles de expresión antes de evaluarlos.

En 2016, la mayoría de los idiomas populares tienen soporte para la expresión lambda , y C # fue uno de los pioneros en esta evolución entre los lenguajes imperativos principales.


La mayoría de las veces, solo estás usando la funcionalidad en un lugar, por lo que hacer que un método simplemente amontone la clase.


Lambda limpió la sintaxis anónima de delegados de C # 2.0 ... por ejemplo

Strings.Find(s => s == "hello");

Fue hecho en C # 2.0 así:

Strings.Find(delegate(String s) { return s == "hello"; });

Funcionalmente, hacen exactamente lo mismo, es solo una sintaxis mucho más concisa.


Las funciones y expresiones anónimas son útiles para métodos únicos que no se benefician del trabajo adicional requerido para crear un método completo.

Considera este ejemplo:

string person = people.Find(person => person.Contains("Joe"));

versus

public string FindPerson(string nameContains, List<string> persons) { foreach (string person in persons) if (person.Contains(nameContains)) return person; return null; }

Estos son funcionalmente equivalentes.


Los encontré útiles en una situación en la que quería declarar un controlador para algún evento de control, usando otro control. Para hacerlo normalmente, tendría que almacenar las referencias de los controles en los campos de la clase para poder usarlos en un método diferente al que fueron creados.

private ComboBox combo; private Label label; public CreateControls() { combo = new ComboBox(); label = new Label(); //some initializing code combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged); } void combo_SelectedIndexChanged(object sender, EventArgs e) { label.Text = combo.SelectedValue; }

Gracias a las expresiones lambda puedes usarlo así:

public CreateControls() { ComboBox combo = new ComboBox(); Label label = new Label(); //some initializing code combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;}; }

Más fácil.


Microsoft nos ha dado una forma más limpia y conveniente de crear delegados anónimos llamados expresiones Lambda. Sin embargo, no se presta mucha atención a la sección de expresiones de esta declaración. Microsoft lanzó un espacio de nombres completo, System.Linq.Expressions , que contiene clases para crear árboles de expresiones basados ​​en expresiones lambda. Los árboles de expresión se componen de objetos que representan la lógica. Por ejemplo, x = y + z es una expresión que podría ser parte de un árbol de expresiones en .Net. Considere el siguiente ejemplo sencillo:

using System; using System.Linq; using System.Linq.Expressions; namespace ExpressionTreeThingy { class Program { static void Main(string[] args) { Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime Console.WriteLine(del(5)); //we are just invoking a delegate at this point Console.ReadKey(); } } }

Este ejemplo es trivial. Y estoy seguro de que estás pensando: "Esto es inútil, ya que podría haber creado directamente al delegado en lugar de crear una expresión y compilarla en tiempo de ejecución". Y tú estarías bien. Pero esto proporciona la base para los árboles de expresión. Hay una serie de expresiones disponibles en los espacios de nombres de Expresiones, y usted puede crear las suyas propias. Creo que puedes ver que esto podría ser útil cuando no sabes exactamente qué algoritmo debe tener en el momento del diseño o la compilación. Vi un ejemplo en algún lugar para usar esto para escribir una calculadora científica. También puede usarlo para sistemas Bayesian o para programación genética (IA). Algunas veces en mi carrera tuve que escribir una funcionalidad similar a Excel que permitía a los usuarios ingresar expresiones simples (sumas, restas, etc.) para operar con los datos disponibles. En pre- .Net 3.5 tuve que recurrir a algún lenguaje de scripting externo a C #, o tuve que usar la funcionalidad de emisión de código en la reflexión para crear código .Net sobre la marcha. Ahora usaría árboles de expresión.


Se ahorra tener que tener métodos que solo se usan una vez en un lugar específico para que no se definan lejos del lugar donde se usan. Los buenos usos son como comparadores de algoritmos genéricos, como la clasificación, donde puede definir una función de ordenación personalizada donde invoca la ordenación en lugar de alejarse, lo que obliga a buscar en otra parte para ver en qué está ordenando.

Y no es realmente una innovación. LISP ha tenido funciones lambda por cerca de 30 años o más.


También puede encontrar el uso de expresiones lambda al escribir códigos genéricos para actuar en sus métodos.

Por ejemplo: Función genérica para calcular el tiempo tomado por una llamada de método. (es decir, Action aquí)

public static long Measure(Action action) { Stopwatch sw = new Stopwatch(); sw.Start(); action(); sw.Stop(); return sw.ElapsedMilliseconds; }

Y puede llamar al método anterior usando la expresión lambda de la siguiente manera,

var timeTaken = Measure(() => yourMethod(param));

La expresión le permite obtener valor de retorno de su método y también fuera de param

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));


Una expresión lambda es como un método anónimo escrito en lugar de una instancia delegada.

delegate int MyDelagate (int i); MyDelagate delSquareFunction = x => x * x;

Considere la expresión lambda x => x * x;

El valor del parámetro de entrada es x (en el lado izquierdo de =>)

La lógica de la función es x * x (en el lado derecho de =>)

El código de una expresión lambda puede ser un bloque de instrucciones en lugar de una expresión.

x => {return x * x;};

Ejemplo

Nota: Func es un delegado genérico predefinido.

Console.WriteLine(MyMethod(x => "Hi " + x)); public static string MyMethod(Func<string, string> strategy) { return strategy("Lijo").ToString(); }

Referencias

  1. ¿Cómo se puede usar indistintamente un delegado y una interfaz?

Las expresiones Lambda son una sintaxis más simple para los delegados anónimos y se pueden usar en cualquier lugar donde se pueda usar un delegado anónimo. Sin embargo, lo contrario no es cierto; Las expresiones lambda se pueden convertir en árboles de expresión, lo que permite una gran cantidad de magia como LINQ to SQL.

El siguiente es un ejemplo de una expresión de LINQ to Objects que usa delegados anónimos y luego expresiones lambda para mostrar cuán fáciles son para el ojo:

// anonymous delegate var evens = Enumerable .Range(1, 100) .Where(delegate(int x) { return (x % 2) == 0; }) .ToList(); // lambda expression var evens = Enumerable .Range(1, 100) .Where(x => (x % 2) == 0) .ToList();

Las expresiones Lambda y los delegados anónimos tienen una ventaja sobre la escritura de una función separada: implementan closures que pueden permitirle pasar el estado local a la función sin agregar parámetros a la función o crear objetos de un solo uso.

Los árboles de expresiones son una nueva característica muy poderosa de C # 3.0 que permite a una API observar la estructura de una expresión en lugar de obtener una referencia a un método que se puede ejecutar. Una API solo tiene que convertir un parámetro de delegado en un parámetro de Expression<T> y el compilador generará un árbol de expresión desde un lambda en lugar de un delegado anónimo:

void Example(Predicate<int> aDelegate);

llamado como

Example(x => x > 5);

se convierte en:

void Example(Expression<Predicate<int>> expressionTree);

El último obtendrá una representación del árbol de sintaxis abstracta que describe la expresión x > 5 . LINQ to SQL se basa en este comportamiento para poder convertir las expresiones C # en las expresiones SQL deseadas para el filtrado / pedido / etc. en el lado del servidor.