CSharp
Tutorial CSharp: Lambdas
Aprende la sintaxis y uso de lambdas en C# para funciones anónimas, colecciones, LINQ y programación asíncrona con ejemplos prácticos.
Aprende CSharp y certifícateSintaxis básica
Las expresiones lambda en C# son una forma concisa de representar funciones anónimas, es decir, métodos sin nombre que pueden definirse en línea. Estas expresiones proporcionan una sintaxis simplificada que resulta especialmente útil cuando necesitamos crear funciones pequeñas y específicas sin tener que declarar un método completo.
La sintaxis básica de una expresión lambda se compone de tres elementos principales:
(parámetros) => expresión_o_bloque
Donde:
- Los parámetros son las entradas que recibe la función
- El operador
=>
(conocido como operador lambda o "va a") - La expresión o bloque que define lo que hace la función
Veamos algunos ejemplos sencillos para entender mejor esta sintaxis:
Lambda con un parámetro
// Lambda que recibe un número y devuelve su cuadrado
Func<int, int> cuadrado = x => x * x;
// Uso:
int resultado = cuadrado(5); // resultado = 25
En este ejemplo, x
es el parámetro de entrada y x * x
es la expresión que se evalúa y devuelve.
Lambda con múltiples parámetros
// Lambda que suma dos números
Func<int, int, int> sumar = (a, b) => a + b;
// Uso:
int suma = sumar(3, 4); // suma = 7
Cuando tenemos más de un parámetro, debemos encerrarlos entre paréntesis.
Lambda sin parámetros
// Lambda sin parámetros que devuelve un saludo
Func<string> saludo = () => "Hola mundo";
// Uso:
string mensaje = saludo(); // mensaje = "Hola mundo"
Lambda con bloque de código
Cuando necesitamos incluir más de una instrucción, podemos usar llaves para crear un bloque de código:
// Lambda con bloque de código
Func<int, int> factorial = n =>
{
int resultado = 1;
for (int i = 1; i <= n; i++)
{
resultado *= i;
}
return resultado;
};
// Uso:
int fact5 = factorial(5); // fact5 = 120
En este caso, como estamos usando un bloque de código con múltiples instrucciones, necesitamos incluir explícitamente la palabra clave return
para devolver un valor.
Tipos de parámetros
En muchos casos, C# puede inferir automáticamente los tipos de los parámetros de la lambda:
// El compilador infiere que x es un entero
Func<int, bool> esPar = x => x % 2 == 0;
Sin embargo, también podemos especificar explícitamente los tipos:
// Especificando explícitamente el tipo del parámetro
Func<int, bool> esPar = (int x) => x % 2 == 0;
Especificar los tipos puede ser necesario en situaciones donde el compilador no puede inferirlos correctamente o cuando queremos mejorar la legibilidad del código.
Captura de variables
Una característica importante de las lambdas es que pueden capturar variables del ámbito donde se definen:
int factor = 10;
Func<int, int> multiplicar = x => x * factor;
int resultado = multiplicar(5); // resultado = 50
En este ejemplo, la lambda captura la variable factor
del ámbito exterior y la utiliza en su expresión.
Las expresiones lambda en C# proporcionan una forma elegante y concisa de definir pequeñas funciones, especialmente útiles cuando necesitamos pasar comportamiento como argumento a otros métodos, como veremos en la siguiente sección sobre "Lambdas como argumentos".
Lambdas como argumentos
Una de las ventajas principales de las expresiones lambda es su capacidad para ser pasadas como argumentos a otros métodos. Esta característica resulta especialmente útil cuando trabajamos con métodos que esperan delegados o interfaces funcionales como parámetros.
En C#, muchos métodos de las colecciones y LINQ (Language Integrated Query) están diseñados para recibir funciones como argumentos, y las lambdas son perfectas para este propósito. Veamos algunos escenarios comunes donde las lambdas brillan como argumentos:
Uso con métodos de colecciones
Las colecciones en C# incluyen varios métodos que aceptan predicados (funciones que devuelven un valor booleano) u otras funciones como argumentos:
List<int> numeros = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Filtrar números pares usando una lambda como argumento
List<int> pares = numeros.FindAll(n => n % 2 == 0);
// pares contiene: 2, 4, 6, 8, 10
En este ejemplo, pasamos la lambda n => n % 2 == 0
como argumento al método FindAll
, que filtra la lista según el predicado proporcionado.
Uso con LINQ
LINQ hace un uso extensivo de las expresiones lambda para definir operaciones sobre colecciones:
var numeros = new[] { 1, 2, 3, 4, 5 };
// Usar lambda con el método Where para filtrar
var mayoresQueTres = numeros.Where(n => n > 3);
// mayoresQueTres contiene: 4, 5
// Usar lambda con Select para transformar elementos
var cuadrados = numeros.Select(n => n * n);
// cuadrados contiene: 1, 4, 9, 16, 25
Aquí, las lambdas definen qué elementos filtrar y cómo transformarlos.
Ordenamiento personalizado
Las lambdas son ideales para definir criterios de ordenamiento personalizados:
List<string> nombres = new List<string> { "Ana", "Carlos", "Beatriz", "David" };
// Ordenar por longitud del nombre usando una lambda
nombres.Sort((a, b) => a.Length.CompareTo(b.Length));
// nombres ahora contiene: "Ana", "David", "Carlos", "Beatriz"
En este caso, la lambda define cómo comparar dos elementos para determinar su orden.
Eventos y callbacks
Las lambdas también son útiles para manejar eventos o definir callbacks:
Button boton = new Button();
// Asignar un manejador de eventos usando una lambda
boton.Click += (sender, e) => {
Console.WriteLine("¡Botón pulsado!");
};
Esta lambda se ejecutará cada vez que ocurra el evento Click del botón.
Métodos de acción asíncrona
En programación asíncrona, las lambdas permiten definir qué hacer cuando una tarea se completa:
Task.Run(() => {
// Código que se ejecuta en segundo plano
Console.WriteLine("Procesando en segundo plano...");
})
.ContinueWith(task => {
// Código que se ejecuta cuando la tarea anterior termina
Console.WriteLine("Procesamiento completado");
});
Delegados predefinidos
C# incluye varios tipos de delegados predefinidos que facilitan el uso de lambdas como argumentos:
// Action - para lambdas que no devuelven valor
Action<string> mostrarMensaje = mensaje => Console.WriteLine(mensaje);
mostrarMensaje("Hola mundo");
// Predicate - para lambdas que devuelven un booleano
Predicate<int> esMayorDeEdad = edad => edad >= 18;
bool adulto = esMayorDeEdad(20); // true
// Comparison - para lambdas que comparan dos valores
Comparison<string> compararLongitud = (s1, s2) => s1.Length.CompareTo(s2.Length);
string[] palabras = { "corto", "larguísimo", "medio" };
Array.Sort(palabras, compararLongitud);
// palabras contiene: "corto", "medio", "larguísimo"
Métodos de extensión personalizados
Podemos crear nuestros propios métodos de extensión que acepten lambdas como argumentos:
public static class ExtensionesEnteros
{
public static int Procesar(this int numero, Func<int, int> procesador)
{
return procesador(numero);
}
}
// Uso:
int resultado = 5.Procesar(n => n * n + 2);
// resultado = 27 (5² + 2)
Ventajas de usar lambdas como argumentos
El uso de lambdas como argumentos ofrece varias ventajas:
- Concisión: Evita tener que definir métodos separados para operaciones simples.
- Claridad: El código es más legible al definir la operación justo donde se usa.
- Contexto local: Las lambdas pueden acceder a variables del ámbito donde se definen.
- Flexibilidad: Permiten personalizar el comportamiento de métodos genéricos.
Las expresiones lambda como argumentos son una herramienta fundamental en C# moderno, especialmente cuando se trabaja con colecciones, LINQ, eventos y programación asíncrona. Dominando esta técnica, podrás escribir código más elegante, conciso y expresivo.
Otros ejercicios de programación de CSharp
Evalúa tus conocimientos de esta lección Lambdas con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
CRUD en C# de modelo Customer sobre una lista
Arrays y listas
Objetos
Excepciones
Eventos
Lambdas
Diccionarios en C#
Variables y constantes
Tipos de datos
Herencia
Operadores
Uso de consultas LINQ
Clases y encapsulación
Uso de consultas LINQ
Excepciones
Control de flujo
Eventos
Diccionarios
Tipos de datos
Conjuntos, colas y pilas
Lambdas
Conjuntos, colas y pilas
Uso de async y await
Tareas
Constructores y destructores
Operadores
Arrays y listas
Polimorfismo
Polimorfismo
Variables y constantes
Proyecto colecciones y LINQ en C#
Clases y encapsulación
Creación de proyecto C#
Uso de async y await
Funciones
Delegados
Delegados
Constructores y destructores
Objetos
Control de flujo
Funciones
Tareas
Proyecto sintaxis en C#
Herencia C Sharp
OOP en C Sharp
Diccionarios
Introducción a C#
Todas las lecciones de CSharp
Accede a todas las lecciones de CSharp y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A C#
Introducción Y Entorno
Creación De Proyecto C#
Introducción Y Entorno
Variables Y Constantes
Sintaxis
Tipos De Datos
Sintaxis
Operadores
Sintaxis
Control De Flujo
Sintaxis
Funciones
Sintaxis
Estructuras De Control Iterativo
Sintaxis
Interpolación De Strings
Sintaxis
Estructuras De Control Condicional
Sintaxis
Manejo De Valores Nulos
Sintaxis
Clases Y Encapsulación
Programación Orientada A Objetos
Objetos
Programación Orientada A Objetos
Constructores Y Destructores
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Genéricos
Programación Orientada A Objetos
Métodos Virtuales Y Sobrecarga
Programación Orientada A Objetos
Clases Abstractas
Programación Orientada A Objetos
Interfaces
Programación Orientada A Objetos
Propiedades Y Encapsulación
Programación Orientada A Objetos
Métodos De Extensión
Programación Orientada A Objetos
Clases Y Objetos
Programación Orientada A Objetos
Clases Parciales
Programación Orientada A Objetos
Miembros Estáticos
Programación Orientada A Objetos
Tuplas Y Tipos Anónimos
Programación Orientada A Objetos
Arrays Y Listas
Colecciones Y Linq
Diccionarios
Colecciones Y Linq
Conjuntos, Colas Y Pilas
Colecciones Y Linq
Uso De Consultas Linq
Colecciones Y Linq
Linq Avanzado
Colecciones Y Linq
Colas Y Pilas
Colecciones Y Linq
Conjuntos
Colecciones Y Linq
Linq Básico
Colecciones Y Linq
Delegados Funcionales
Programación Funcional
Records
Programación Funcional
Expresiones Lambda
Programación Funcional
Linq Funcional
Programación Funcional
Fundamentos De La Programación Funcional
Programación Funcional
Pattern Matching
Programación Funcional
Testing Unitario Con Xunit
Testing
Excepciones
Excepciones
Delegados
Programación Asíncrona
Eventos
Programación Asíncrona
Lambdas
Programación Asíncrona
Uso De Async Y Await
Programación Asíncrona
Tareas
Programación Asíncrona
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender la sintaxis básica de las expresiones lambda en C#.
- Aprender a definir lambdas con diferentes números de parámetros y bloques de código.
- Entender la inferencia de tipos y la captura de variables en lambdas.
- Conocer cómo utilizar lambdas como argumentos en métodos, especialmente en colecciones y LINQ.
- Identificar las ventajas y aplicaciones prácticas de las lambdas en programación moderna en C#.