Un delegate è un riferimento type-safe a un metodo (come un puntatore a funzione) — ti permette di trattare i metodi come dati: memorizzarli, passarli come argomenti e invocarli. Gli events sono un pattern costruito sui delegate per il modello publish-subscribe (observer). Sono alla base dei callback, LINQ e della programmazione event-driven in C#.
Delegate — metodi come valori
// a delegate type defines a method signature
public delegate int Operation(int a, int b);
Operation add = (a, b) => a + b; // assign a method/lambda to it
Operation multiply = (a, b) => a * b;
int result = add(2, 3); // invoke → 5
// pass a delegate as an argument (higher-order function)
int Apply(Operation op, int x, int y) => op(x, y);
Apply(multiply, 4, 5); // 20
Un delegate contiene un riferimento a un metodo che corrisponde alla sua firma, permettendo ai metodi di essere passati e invocati dinamicamente.
Tipi di delegate built-in (usa questi, non quelli personalizzati)
Func<int, int, int> add = (a, b) => a + b; // Func — takes args, RETURNS a value
Action<string> log = msg => Console.WriteLine(msg); // Action — returns VOID
Predicate<int> isPositive = n => n > 0; // Predicate — returns bool
// used heavily in LINQ and APIs:
list.Where(x => x > 0).Select(x => x * 2); // lambdas are delegates
Nel C# moderno, di solito usi i Func<> built-in (restituisce un valore), Action<> (restituisce void), e Predicate<> piuttosto che dichiarare tipi di delegate personalizzati. Le lambda (x => ...) creano delegate — la base di LINQ.
Events — il pattern publish-subscribe
public class Button
{
public event EventHandler Clicked; // an EVENT (based on a delegate)
public void Click() => Clicked?.Invoke(this, EventArgs.Empty); // raise it
}
var button = new Button();
button.Clicked += (sender, e) => Console.WriteLine("clicked!"); // SUBSCRIBE (+=)
button.Clicked -= handler; // unsubscribe (-=)
Un event avvolge un delegate per fornire un pub-sub sicuro: i subscriber registrano handler con +=, il publisher lancia l'event (Invoke), e tutti gli handler vengono eseguiti. Gli events limitano il codice esterno a solo sottoscriversi/annullare l'iscrizione (non lanciare o svuotare) — incapsulamento per il pattern observer.
Perché è importante
I delegate e gli events sono caratteristiche importanti di C# che consentono di trattare i metodi come dati, callback e programmazione event-driven — e comprenderli è prezioso sia per usarli che per afferrare come funziona gran parte di C# e .NET. I delegate (riferimenti type-safe ai metodi) sono la base: permettono ai metodi di essere memorizzati, passati e invocati dinamicamente, il che è alla base di LINQ (le lambda passate a Where/Select sono delegate), callback e programmazione in stile funzionale.
Sapere di usare i tipi di delegate built-in Func<>/Action<>/Predicate<> (piuttosto che dichiararne di personalizzati) è conoscenza pratica, quotidiana, poiché compaiono in tutto il framework e sono il modo in cui passi il comportamento a LINQ e molte API. Gli events si basano sui delegate per implementare il pattern publish-subscribe (observer) in modo sicuro — è come C# gestisce scenari event-driven (event UI, notifiche, comunicazione disaccoppiata), con +=/-= per sottoscriversi/annullare l'iscrizione.
Comprendere i delegate (specialmente Func/Action e le lambda, la base di LINQ), e gli events (il pattern pub-sub per il codice disaccoppiato e event-driven) è importante per lavorare efficacemente con C#, poiché queste caratteristiche sono alla base di LINQ, callback e gestione degli event che compaiono costantemente.
Padroneggiare questi concetti — in particolare riconoscere che le lambda sono delegate e come abilitano LINQ e i pattern funzionali — è conoscenza frequentemente applicata che riflette la comprensione delle capacità funzionali di C# e del modello event-driven, ed è un argomento comune nei colloqui.
