foreach中匿名代理的问题 [英] Problem with anonymouse delegate within foreach

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

问题描述

公开Form1()
{
InitializeComponent();

  
集合<测试> tests = new Collection< Test>();
tests.Add(new Test(test1));
tests.Add(new Test(test2));
foreach(测试中的测试)
{
按钮按钮=新的Button();
button.Text = test.name;
button.Click + = new EventHandler((object obj,EventArgs arg)=> {
this.CreateTest(test);
});
this.flowLayoutPanel1.Controls.Add(button);
}
}
public void CreateTest(测试测试)
{
MessageBox.Show(test.name);
}
}

当我点击按钮女巫文本是'test1'消息框将显示'test2',但我的期望是'test1'。
所以,有人请告诉我为什么或什么问题我的代码。

解决方案

关闭循环变量。 lambda表达式中的测试表示所有代理中的相同变量,这意味着它将在循环结束时以最终值结尾。拿一个价值的副本并使用它。你也使用了一个漂亮的longwinded形式的lambda表达式。以下是固定和缩短的代码:

  foreach(测试中的测试)
{
//取test变量的副本,以便每次迭代
//创建一个代理捕获不同的变量(因此一个
//不同的值)
Test copy = test;
按钮按钮= new Button();
button.Text = test.name;
button.Click + =(obj,arg)=> CreateTest(copy);
this.flowLayoutPanel1.Controls.Add(button);
}

请参阅 Eric Lippert关于这个主题的博客,以获取更多信息。 >

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

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 - 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天全站免登陆