Nick ha ragione, ma ho voluto spiegare un po 'meglio nel testo di questa domanda esattamente perché.
Il problema non è la chiusura; è il ciclo for. Il ciclo crea solo una variabile "i" per l'intero ciclo. Non crea una nuova variabile "i" per ogni iterazione. Nota: Questo ha riferito cambiato per C# 5.
Questo significa che quando il delegato anonima cattura o chiude su quella "i" variabile Si sta chiudendo su una variabile che è condivisa da tutti i pulsanti. Nel momento in cui effettivamente si fa clic su uno di questi pulsanti, il ciclo ha già completato l'incremento di tale variabile fino a 7.
L'unica cosa che potrei fare in modo diverso dal codice di Nick è usare una stringa per la variabile interna e costruire tutte quelle corde in anticipo, piuttosto che al momento della pressione del pulsante, in questo modo:
for (int i = 0; i < 7; i++)
{
var message = string.Format("I am button number {0}.", i);
Button newButton = new Button();
newButton.Text = "Click me!";
newButton.Click += delegate(Object sender, EventArgs e)
{
MessageBox.Show(message);
};
this.Controls.Add(newButton);
}
Che proprio commercia un po 'di memoria (tenendo conto di variabili stringa più grandi invece di numeri interi) per un po' di tempo in poi della cpu ... dipende dalla vostra applicazione ciò che conta di più.
Un'altra opzione è quella di non codificare manualmente il circuito a tutti:
this.Controls.AddRange(Enumerable.Range(0,7).Select(i =>
{
var b = new Button() {Text = "Click me!", Top = i * 20};
b.Click += (s,e) => MessageBox.Show(string.Format("I am button number {0}.", i));
return b;
}).ToArray());
Mi piace questa ultima opzione non tanto perché rimuove l'anello, ma perché inizia pensando in termini di costruzione di questa regola da un fonte di dati.
fonte
2010-02-09 04:09:57
Non si acquisisce il valore. Non acquisisci mai valori, solo variabili. Per ulteriori informazioni su questo problema, vedere http://blogs.msdn.com/ericlippert/archive/2009/11/12/close-over-the-loop-variable-considered-harmful.aspx e http: //blogs.msdn .com/ericlippert/archive/2009/11/16/closing-over-the-loop-variable-part-two.aspx –