CodeGym /Cursos /C# SELF /Expresiones lambda para even...

Expresiones lambda para event y callback

C# SELF
Nivel 50 , Lección 3
Disponible

1. Introducción

En C# (y en .NET en general) los eventos son una de las formas en que los objetos se comunican entre sí. Por ejemplo, tienes un botón cuyo clic debe disparar algo. Podrías implementar el manejo de eventos declarando un método aparte y luego suscribir ese método al evento... Pero muchas veces quieres simplemente “describir la reacción aquí mismo”, sin esparcir la lógica por distintas partes del archivo.

Las expresiones lambda resuelven esto de maravilla: permiten literalmente escribir la reacción al evento en el mismo lugar donde te suscribes. Mínima ceremonia — máximo beneficio.

Lo mismo aplica para los callbacks: a veces pasas a un método cierta lógica para ejecutar “más tarde”, por ejemplo cuando una operación termine, y otra vez — las lambdas lo hacen simple y explícito: toda la lógica necesaria está justo en el sitio de la llamada.

Eventos y callbacks: lo esencial y dónde vienen bien las lambdas

Evento — no es más que un “cartel” en un objeto: “aquí alguien puede suscribirse y hacer algo cuando ocurra algo”.

Callback (llamada de retorno) — es “te doy ahora una función y la llamas cuando haga falta”. Muy parecido a “deja tu solicitud — te llamamos”.

Cuando aprendiste sobre delegates y eventos antes, ya viste una sintaxis más o menos así:

button.Click += MyButtonClickHandler;

Donde MyButtonClickHandler es un método concreto que debes declarar en algún sitio. Pero cuando la lógica es simple, quieres arreglártelas con un par de líneas sin crear métodos por una sola acción.

Ahí es donde entran en escena las lambdas:

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

Conciso, claro, ¡justo aquí mismo!

2. Lambdas como manejadores de eventos: de lo simple a lo interesante

Forma simple: la bombilla parpadeó — mostramos algo en la consola

Supongamos que tenemos la clase Button, y queremos reaccionar a su evento Click.

// Imaginemos un botón así:
public class Button
{
    public event EventHandler? Click;

    public void SimulateClick() // Para el ejemplo: "hacemos click" programáticamente
    {
        // Si alguien está suscrito — llamamos a los manejadores
        Click?.Invoke(this, EventArgs.Empty);
    }
}

Ahora usamos ese botón:

var button = new Button();

// ¡Nos suscribimos al evento del botón usando una lambda!
button.Click += (sender, args) =>
{
    Console.WriteLine("¡Hurra! ¡Se pulsó el botón!");
};

button.SimulateClick(); // => ¡Hurra! ¡Se pulsó el botón!

Explicación:
— Todo lo que va después de => es el cuerpo de tu “mini-función”, que se ejecutará cuando ocurra el evento.
— No hace falta preocuparse por el ciclo de vida del manejador: vive mientras viva tu suscripción (+=). Importante: si la lambda captura variables externas y no te desuscribes del evento, eso puede causar memory leaks.

Manejador lambda con captura de variables

int clickCount = 0;

button.Click += (sender, args) =>
{
    clickCount++;
    Console.WriteLine($"¡El botón se ha pulsado ya {clickCount} vez(veces)!");
};

button.SimulateClick(); // => ¡El botón se ha pulsado ya 1 vez(veces)!
button.SimulateClick(); // => ¡El botón se ha pulsado ya 2 vez(veces)!

Qué ocurre:
La lambda "captura" la variable clickCount externa y recuerda su valor entre llamadas.

3. Uso de expresiones lambda para callbacks

Callback se usa a menudo cuando cierto código debe llamar a tu función más tarde — por ejemplo, después de completar un trabajo pesado.

Pasar una lambda como callback

Supongamos que tenemos un método que acepta un delegate o una lambda como argumento:

void DoWork(Action callback)
{
    Console.WriteLine("Empieza el trabajo...");
    // Simulación de trabajo
    System.Threading.Thread.Sleep(500); // (¡No hagas esto en aplicaciones reales, es bloqueante!)
    callback(); // Tras el trabajo llamamos al callback
}

DoWork(() => Console.WriteLine("¡Trabajo terminado!"));

Resultado:
Primero aparecerá en la consola "Empieza el trabajo...", luego "¡Trabajo terminado!".

Puedes pasar lambdas con parámetros:

void Calculate(int a, int b, Action<int> onResult)
{
    int sum = a + b;
    onResult(sum);
}

Calculate(5, 8, result => Console.WriteLine($"Resultado: {result}"));

4. Errores típicos al usar lambdas

No desuscribirse de eventos

Cuando te suscribes a un evento con una lambda, no tienes un “nombre de manejador” para desuscribirte fácilmente:

button.Click += (s, e) => Console.WriteLine("...");
button.Click -= ??? // ¿Cómo pasar aquí tu lambda? No se puede, si no la guardaste.

Si necesitas desuscribirte — guarda la lambda en una variable:

EventHandler handler = (s, e) => Console.WriteLine("...");
button.Click += handler;
// ... luego
button.Click -= handler;

Esto es importante para objetos de larga vida: si no te desuscribes, la referencia puede quedarse y posiblemente causar memory leaks.

Captura de la variable del bucle

Clásico: suscribirse a eventos dentro de un bucle:

for (int i = 0; i < 3; i++)
    button.Click += (s, e) => Console.WriteLine(i); // Todas las lambdas "recuerdan" el mismo i

En versiones modernas de C# este comportamiento se corrigió para foreach, pero para for a veces pueden haber matices — ¡siempre ten cuidado con las variables capturadas!

Si necesitas que cada lambda recuerde su propio valor — crea una copia local:

for (int i = 0; i < 3; i++)
{
    int localI = i;
    button.Click += (s, e) => Console.WriteLine(localI);
}
2
Tarea
C# SELF, nivel 50, lección 3
Bloqueada
Contador de clics con captura de variables
Contador de clics con captura de variables
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION