Problem with Anonymous delegate in loop

   1: foreach (Test test in tests)
   2:             {
   3:                 Button button = new Button();
   4:                 button.Text = test.name;
   5:                 button.Click+=new EventHandler((object obj, EventArgs arg)=>{
   6:                     this.CreateTest(test);
   7:                 });
   8:                 this.flowLayoutPanel1.Controls.Add(button);
   9:             }

tests裏有2個元素,分別爲test1與test2, 程序會爲每個test新建一個button, 設爲button1,button2.
在button1的Click事件觸發的時候,調用CreateTestFlow方法時,傳遞的參數會是test2而不是test1.

image

原因:

WTF: "Problems" with Anonymous Delegates, LINQ, Lambdas within "foreach" or "for" Loops這篇文章裏的解釋爲:匿名委託裏的test是對循環變量引用,在循環結束時該變量爲最後個值,即’test2’.
如對foreach的理解相對困難的話,可以把foreach改爲for,代碼如下:

   1: for (int i=0;i<tests.Count;i++)
   2: {
   3:     Button button = new Button();
   4:     button.Text = tests[i].name;
   5:     button.Click+=new EventHandler((object obj, EventArgs arg)=>{
   6:         this.CreateTest(tests[i]);
   7:     });
   8:     this.flowLayoutPanel1.Controls.Add(button);
   9: }

則此代碼在運行時,會在第6行出現:ArgumentOutOfRangeException, Index was out of range.

解決方法:

在循環體裏新建一變量,用來保存循環過程中的值。代碼如下:

   1:  foreach (Test tes in tests)
   2:             {
   3:                 Test test = tes;
   4:                 Button button = new Button();
   5:                 button.Text = test.name;
   6:                 button.Click+=new EventHandler((object obj, EventArgs arg)=>{
   7:                     this.CreateTest(test);
   8:                 });
   9:                 this.flowLayoutPanel1.Controls.Add(button);
  10:             }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章