在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)[重复]

欺骗C编译器将整个结构分配为零,没有for循环[重复]

For循环正在覆盖列表中的字典值[重复]

在 for 循环的每个循环中分配标签

c++ 在 for 循环中的 vector<char> 中的 for 循环中的内存分配

如何通过for循环将矩阵的值分配给数组