在for循环中分配代表的问题[重复]
Posted
技术标签:
【中文标题】在for循环中分配代表的问题[重复]【英文标题】:Problem with assigning delegates in for-loop [duplicate] 【发布时间】:2010-07-13 13:09:54 【问题描述】:我有一个支持插件 (MEF) 的应用程序。 插件是导入服务的 WPF 用户控件。
用户可以从应用程序的主菜单中选择想要的插件。
为此,我使用以下循环:
foreach(IToolPlugin Plugin in ToolPlugins)
Plugin.Init();
MenuItem PluginMenuItem = Plugin.MenuItem; //New MenuItem but with Header set.
PluginMenuItem.Click += new RoutedEventHandler(delegate(object o, RoutedEventArgs e) DoSomething(Plugin.Control););
PluginsMenu.Items.add(PluginMenuItem);
这对于单个项目非常有效。但是只要我有超过 1 个插件,所有菜单项都会执行最后一个循环的委托。或者至少使用最后一个循环的 Plugin.Control。
我该如何解决这个问题? 感谢您的帮助。
【问题讨论】:
我喜欢看到这个问题的许多变化。 @Chaos - 在这种情况下你应该投票关闭 ;) 【参考方案1】:在循环的每次迭代中,您必须先“捕获”迭代值的值,然后才能在闭包中使用它。否则,每个委托中的 Plugin 将指向 Plugin 的最后一个值,而不是它在创建匿名函数时所持有的值。
您可以在此处阅读 Eric Lippert 的更深入解释:
Closing over the loop variable considered harmful - Fabulous Adventures in Coding
简而言之,编写 foreach 循环的正确方法是:
foreach(IToolPlugin Plugin in ToolPlugins)
Plugin.Init();
MenuItem PluginMenuItem = Plugin.MenuItem;
IToolPlugin capturedPlugin = Plugin;
PluginMenuItem.Click +=
new RoutedEventHandler(delegate(object o, RoutedEventArgs e)
DoSomething(capturedPlugin.Control);
);
PluginsMenu.Items.add(PluginMenuItem);
【讨论】:
我假设您将包含指向 Eric 关于此事的博客文章的强制性链接? (关闭被认为有害的循环变量。) 我们应该有一个关于这个问题的列表 :) (由于很难搜索,我认为不值得将其作为副本关闭。) @Jon Skeet - 很难说。我刚刚快速搜索了 c#closure foreach 并获得了大量点击(还在问题中添加了闭包标签)。我认为部分问题在于人们没有意识到这些是闭包。 当然。如果你知道这是一个关闭,那么你就成功了一半。以上是关于在for循环中分配代表的问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章
增强的 for 循环不适用于将值分配给数组(Java)[重复]