Per il exact definition, I suggest looking at its Wikipedia entry. È particolarmente buono. Voglio solo chiarirlo con un esempio.
assumersi questa C# frammento di codice (questo dovrebbe eseguire una ricerca AND
in una lista):
List<string> list = new List<string> { "hello world", "goodbye world" };
IEnumerable<string> filteredList = list;
var keywords = new [] { "hello", "world" };
foreach (var keyword in keywords)
filteredList = filteredList.Where(item => item.Contains(keyword));
foreach (var s in filteredList) // closure is called here
Console.WriteLine(s);
E 'un errore comune in C# per fare qualcosa di simile. Se si guarda l'espressione lambda all'interno di Where
, si noterà che definisce una funzione il cui comportamento dipende dal valore di una variabile nel suo sito di definizione. È come passare una variabile stessa alla funzione, anziché il valore di tale variabile. In effetti, quando viene chiamata questa chiusura, recupera il valore della variabile keyword
in quel momento. Il risultato di questo esempio è molto interessante.Stampa sia "ciao mondo" e "arrivederci mondo", che non è quello che volevamo. Quello che è successo? Come detto in precedenza, la funzione abbiamo dichiarato con l'espressione lambda è una chiusura sopra keyword
variabile quindi questo è ciò che accade:
filteredList = filteredList.Where(item => item.Contains(keyword))
.Where(item => item.Contains(keyword));
e al momento dell'esecuzione chiusura, keyword
ha il valore mondo" , "quindi stiamo fondamentalmente filtrando la lista un paio di volte con la stessa parola chiave. La soluzione è:
foreach (var keyword in keywords) {
var temporaryVariable = keyword;
filteredList = filteredList.Where(item => item.Contains(temporaryVariable));
}
Da temporaryVariable
ambito la corpo del ciclo foreach
, in ogni iterazione, è una variabile diversa. In effetti, ogni chiusura si legherà a una variabile distinta (quelle sono istanze differenti di temporaryVariable
ad ogni iterazione). Questa volta, darà i risultati corretti ("ciao mondo"):
filteredList = filteredList.Where(item => item.Contains(temporaryVariable_1))
.Where(item => item.Contains(temporaryVariable_2));
in cui temporaryVariable_1
ha il valore di "ciao" e temporaryVariable_2
ha il valore "mondo" al momento dell'esecuzione di chiusura.
Si noti che le chiusure hanno causato un'estensione della durata delle variabili (la loro vita doveva terminare dopo ogni iterazione del ciclo). Questo è anche un importante effetto collaterale delle chiusure.
Wikipedia è particolarmente buono a definizioni: http://en.wikipedia.org/wiki/Closure_%28computer_science%29 –
Tuttavia, come definizioni di Wikipedia questo tende ad essere scritto da fanatici di stress da pipa e da weenies di cristallografia (cioè non sono sempre gli uccelli più facili da capire). –
L'articolo di Wikipedia era uno che ho letto. Dice che qualsiasi funzione di prima classe con variabili libere è una chiusura. Ciò non ha alcun senso, anche perché include tutte le funzioni di prima classe che restituiscono valori basati sui loro argomenti. Sta implicando che diventa una chiusura quando la funzione usa variabili libere per istanziare le sue variabili associate? – Amaron