Closure e variabili catturate
In C# è possibile definire delle funzioni in linea e utilizzarle come tutte le altre variabili ovvero passarle come parametri ai metodi, restituirle come risultato di un metodo e in più, essendo funzioni, possiamo invocarle.
Uno scenario ricorrente in questi casi, sicuramente familiare a chi ha utilizzato LINQ in una delle sue tante forme, è quella di utilizzare all'interno di una lambda expression una variabile definita nel contesto padre della lambda stessa.
Un esempio può essere
var listaInteri = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int limite = 5; var sottoLimite = listaInteri.Where(p => p < limite);
La lambda expression che passiamo come argomento della Where fa riferimento alla variabile limite definita al di fuori della lambda e nel contesto padre. Cosa succede se ampliamo lo snippet precedente in questo modo
var listaInteri = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int limite = 5; var sottoLimite = listaInteri.Where(p => p < limite); limite = 8; var risultato = sottoLimite.ToList();
Sappiamo tutti che la Where LINQ ha un'esecuzione differita, quindi la variabile "sottoLimite" non contiene il risultato della query ma la query stessa che verrà effettuata solo nel momento in cui verrà effettuata una enumerazione della variabile.
Il ToList() esegue la query e quale sarà il contenuto della variabile risultato? Ebbene conterrà i valori da 1 a 7.
Cosa è successo?
La lambda expression che abbiamo passato come parametro del metodo Where ha "catturato" la variabile limite e non solamente il suo valore nel momento della definizione. Quello che succede è che ogni volta che utilizzeremo la lambda expression essa utilizzerà il valore più aggiornato della variabile totale e la vita della variabile totale è estesa alla vita della lambda. Finché ci sarà un riferimento alla lambda anche la variabile limite sarà ancora "viva".
Questo procedimento di cattura è chiamato "closure", nel caso di C# quello che succede è che il compilatore genera una classe che conterrà la funzione catturatrice e tutte le variabili catturate.