问题用foreach内匿名者代表 [英] Problem with anonymouse delegate within foreach

查看:99
本文介绍了问题用foreach内匿名者代表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

    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);
    }
}

,消息框将显示test2,但我的期望是test1。

when i click the button witch text is 'test1', the messagebox will show 'test2',but my expect is 'test1'. So ,would anyone please tell me why or what`s wrong with my code.

推荐答案

Yup - 你'重新关闭循环变量。 lambda表达式中的 test 是指所有代理中的同一个变量,这意味着它将在循环结束时以最终值结束。取一个值的副本并使用它。你也使用一个很长的lambda表达式形式。下面是固定和缩短的代码:

Yup - you're closing over the loop variable. The test within the lambda expression refers to the same variable in all your delegates, which means it will end up with the final value at the end of the loop. Take a copy of the value and use that. You're also using a pretty longwinded form of the lambda expression. Here's the fixed and shortened code:

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);
}

查看

See Eric Lippert's blog post on this topic for more information.

这篇关于问题用foreach内匿名者代表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆