CodeGym /Cursos /C# SELF /Sintaxis de las expresiones lambda (

Sintaxis de las expresiones lambda ( =>)

C# SELF
Nivel 49 , Lección 1
Disponible

1. Introducción

Puede que no lo supieras, pero una de las preguntas favoritas en entrevistas es: “¿Qué sabes sobre las expresiones lambda?”. ¿Por qué la preguntan? Porque es una cosa muy cómoda y "de moda" en C#, que permite escribir menos código y hacerlo más expresivo. Si los métodos anónimos son como escribir una carta a mano, las expresiones lambda son como enviar un mensaje por un messenger: rápido, compacto y a veces hasta con emoticonos (bueno, casi).

Las expresiones lambda llegaron a C# con la versión 3.0 y desde entonces se han propagado por todas partes: en LINQ, manejadores de eventos, hilos, colecciones e incluso bibliotecas de inteligencia artificial en .NET.

Una expresión lambda es una forma de declarar un método directamente en el cuerpo del código, "in situ", sin nombre, súper corta y clara. La sintaxis básica siempre se ve así:

(parámetros) => expresión_o_bloque_de_código

Esta "flecha" => se llama “operador lambda” o “flecha”.

Pequeña analogía

Recuerda cómo escribes una receta: “Tomar una manzana, cortarla, ponerla en un bol”.
En C# sería:

(manzana) => cortar(manzana)

2. Convertimos un método anónimo a una lambda

Supongamos que tenemos un delegado:

delegate int SquareDelegate(int x);

Un método anónimo se vería así:

SquareDelegate sq = delegate(int x) {
    return x * x;
};

Y ahora lo mismo con una expresión lambda:

SquareDelegate sq = (int x) => { return x * x; };

Pero C# puede inferir los tipos, y podemos acortarlo todavía más:

SquareDelegate sq = x => x * x;

¡Qué compacta y genial!

Comparación con un método "normal" y una función anónima

Método Declaración Dónde usar Contras
Método nombrado En la clase En cualquier sitio Necesita nombre, más código
Método anónimo En el código Sólo con delegados Sintaxis más verbosa
Expresión lambda En el código En cualquier sitio con delegados A veces el tipo no es obvio

3. Sintaxis de la expresión lambda: variaciones

Parámetros

Sin parámetros:

Action hello = () => Console.WriteLine("¡Hola, mundo!");

Un parámetro (puedes omitir los paréntesis):

Func<int, int> inc = x => x + 1;

Varios parámetros (se necesitan paréntesis):

Func<int, int, int> sum = (a, b) => a + b;

Cuerpo de la lambda

Una sola expresión — sin llaves y sin return:

x => x * x

Bloque de código — llaves y necesitas return:

(x, y) =>
{
    int z = x + y;
    return z * z;
}

Tipos de parámetros

La mayoría de las veces no hace falta especificar el tipo — el compilador lo infiere. Pero si quieres, puedes:

(x, y) => x + y      // El compilador infiere los tipos.
(int x, int y) => x + y  // Puedes especificarlos explícitamente.

4. Matices y ejemplos más reales

Uso con colecciones

Recuerda nuestra mini-aplicación de ejemplo (por ejemplo, una lista de usuarios). Supongamos que tenemos un array de números:

int[] numbers = { 1, 2, 3, 4, 5 };

Queremos seleccionar solo los números pares:

var evenNumbers = numbers.Where(n => n % 2 == 0);

Aquí Where es un método de extensión de LINQ, y la condición es nuestro filtro lambda.

Pasar a un método

Supongamos que tenemos un método delegado:

public delegate bool Filter(int number);

public static int[] FilterNumbers(int[] data, Filter predicate)
{
    var result = new List<int>();
    foreach (var n in data)
        if (predicate(n))
            result.Add(n);
    return result.ToArray();
}

Ahora pasamos una expresión lambda:

int[] evens = FilterNumbers(numbers, n => n % 2 == 0);

Lambda como manejador de eventos

button.Click += (sender, args) => Console.WriteLine("¡Botón pulsado!");

5. Lambdas y los delegados genéricos estándar

Es difícil imaginar las lambdas sin Func<>, Action<> y Predicate<>. Son tipos especiales de delegados:

  • Action — no devuelve nada.
  • Func — devuelve un valor.
  • Predicate — devuelve bool, normalmente para filtrado.

Ejemplo con Action:

Action<string> log = message => Console.WriteLine(message);

log("¡Este mensaje a través de una lambda!");

Ejemplo con Func:

Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15

Ejemplo con Predicate:

Predicate<int> isNegative = n => n < 0;

bool test = isNegative(-7); // true

6. Lambdas con múltiples expresiones: cuándo usar un bloque

Si la lambda debe ejecutar varias operaciones, usa llaves y un return explícito:

Func<int, int, string> describeSum = (a, b) =>
{
    int sum = a + b;
    return $"Suma: {sum}";
};

Sin return el compilador se quejará (pero no siempre explica bien por qué — simplemente dirá que "no todos los caminos devuelven un valor").

7. Devolver void: Action

Cuando la lambda no devuelve nada, usa Action:

Action greet = () => Console.WriteLine("¡Sonríe — el código compila!");

La lambda puede contener tantas instrucciones como quieras:

Action<int> printSquare = x =>
{
    int sq = x * x;
    Console.WriteLine($"El cuadrado de {x} es {sq}");
};

8. Limitaciones y errores típicos

A veces quieres escribir una lambda muy libremente, pero el compilador no siempre está de acuerdo.

No puedes declarar una variable con el mismo nombre que una variable capturada desde el exterior.

Hay que vigilar los tipos: si la firma del delegado y la lambda no coinciden — habrá error.

El retorno de valor es obligatorio si el delegado requiere un valor de retorno.

En lambdas complejas no olvides las llaves. Una sola expresión — sin llaves y sin return. Varias instrucciones — llaves y return.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION