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.
原因:
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: }