如何避免lambda表达式中的变量捕获?

Ziv*_*Ziv 4 c# lambda


最近我在深度阅读了C#,它教会了我关于lambda表达式的知识,我一直在使用它来将数据传递给点击事件,例如:

image.MouseDown+=(o ,e)=>MethodToDoSomething(DataNeededForAction);
Run Code Online (Sandbox Code Playgroud)

现在问题是在foreach循环中使用变量捕获(感谢Jon Skeet使这部分非常清楚:),当初始化具有我订阅的事件的几个对象时,我通常遇到变量捕获的问题.考虑以下示例:

foreach (var game in GamesCollection)
{
    Image img = new Image();
    img.Width = 100;
    img.MouseDown+=(o,e) => MyMethod(game.id);
}
Run Code Online (Sandbox Code Playgroud)

为了避免在这种情况下捕获,我必须添加一些变量来分配游戏,然后将该变量传递给方法,这会产生额外的不清楚的代码,主要是额外的混乱.有没有办法绕过这个?什么东西至少看起来更干净?

Thx,Ziv

Jon*_*eet 5

(编辑:请注意,这已经改变了C#5,foreach现在有效地为每次迭代创建一个新变量.)

不,没有办法避免这种情况.基本上,语言规范foreach在单个变量方面描述的方式是错误的,而不是每次迭代的新变量.就个人所涉及的代码数量而言,我个人并不认为这是一个问题 - 当你意识到这是一个问题并想出如何修复它时,你已经克服了最大的障碍.我想通常会包含一条评论,以便让维护程序员明白这一点.

我敢肯定,如果他们从头开始,C#团队会采用不同的方式,但事实并非如此.哎呀,他们甚至讨论过改变现有的行为 ......但是有充分的理由反对这种改变(特别是在C#N + 1编译器上正常工作的代码仍会编译,但在C#N编译器上给出了错误的结果;开源库作者的一个非常微妙的漏洞来源,他们期望用多个编译器构建代码.

(希望你喜欢这本书,顺便说一句......)