2010-04-03 7 views
4
public Form1() 
    { 
     InitializeComponent(); 
     Collection<Test> tests = new Collection<Test>(); 
     tests.Add(new Test("test1")); 
     tests.Add(new Test("test2")); 
     foreach (Test test in tests) 
     { 
      Button button = new Button(); 
      button.Text = test.name; 
      button.Click+=new EventHandler((object obj, EventArgs arg)=>{ 
       this.CreateTest(test); 
      }); 
      this.flowLayoutPanel1.Controls.Add(button); 
     } 
    } 
    public void CreateTest(Test test) 
    { 
     MessageBox.Show(test.name); 
    } 
} 

lorsque je clique sur le bouton dont le texte est 'test1', la boîte de message montrera 'test2', mais mon attente est 'test1'. Donc, quelqu'un s'il vous plaît dites-moi pourquoi ou ce qui ne va pas avec mon code.Problème avec délégué anonymouse dans foreach

Répondre

14

Yup - vous fermez la variable de boucle. Le test dans l'expression lambda se réfère à la même variable dans tous vos délégués, ce qui signifie qu'il finira avec la valeur finale à la fin de la boucle. Prenez une copie de la valeur et utilisez-la. Vous utilisez également une forme assez longue de l'expression lambda. Voici le code fixe et raccourci:

foreach (Test test in tests) 
{ 
    // Take a copy of the "test" variable so that each iteration 
    // creates a delegate capturing a different variable (and hence a 
    // different value) 
    Test copy = test; 
    Button button = new Button(); 
    button.Text = test.name; 
    button.Click += (obj, arg) => CreateTest(copy); 
    this.flowLayoutPanel1.Controls.Add(button); 
} 

Voir Eric Lippert's blog post on this topic pour plus d'informations.

+0

Merci beaucoup. – geting

Questions connexes