c# - 作用范围参数

标签 c# wpf scope action

我一直在开发一个 WPF 应用程序,并且偶然发现了一些有趣的东西,可能是因为我不知道它到底是如何工作的。

基本上我正在创建一个上下文菜单。该菜单有一个父 MenuItem,它有 3 个相同类型的子菜单项。这是最基本的代码。

public MainWindow()
{
    InitializeComponent();

    ContextMenu ctxMain = new ContextMenu();

    MenuItem parent = CreateMenuItem("Parent", null);

    for(int i = 0; i < 3; i++)
    {
        parent.Items.Add(CreateMenuItem(i.ToString(), () => MessageBox.Show(i.ToString())));
    }

    ctxMain.Items.Add(parent);
    this.ContextMenu = ctxMain;
}


public MenuItem CreateMenuItem(string header, Action action)
{
    MenuItem item = new MenuItem();
    if (action != null)
    {
        item.Click += (object sender, RoutedEventArgs e) => action();
    }
    item.Header = header;
    return item;
}

从视觉上看,它按预期工作。

但是我作为参数给出的操作表现得很奇怪。我希望每个子项的单击都能显示 MessageBox 中其标题中所写的内容。但它们都显示“3”。

我是否理解正确,我在 for 循环中定义的内联操作不会使用相同的参数“i”实例化三次,而只会实例化一次?或者它们是三个不同的 Action 实例,都引用同一个整数?我想听听对这里发生的事情的一些澄清。

提前致谢。 问候。

最佳答案

for(int i = 0; i < 3; i++)
{
    var localCopy = i;
    parent.Items.Add(CreateMenuItem(localCopy.ToString(), () => MessageBox.Show(localCopy.ToString())));
}

你的变量 i 被 lambda 表达式“捕获”。但在执行您的操作之前,i 已经发生了变化。并且您的操作在当前的 i 上执行,这意味着 3(循环之后以及您的操作最终执行时 i 的值)。

您需要制作变量的本地副本并使用它。由于它在循环内有自己的作用域,因此永远不会改变。

关于c# - 作用范围参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32070568/

相关文章:

java - 由于缺少变量导致的编译器错误(变量在不同的类中定义)

c# - 在 C# UWP 中创建 Web 服务器

c# - 从 sharepoint 2010 服务器读取文件夹和文件属性,例如 UniqueId

c# - 我可以将控件的内联样式移动到不同的文件吗?

wpf ComboBox异步绑定(bind)到项目源问题

javascript - 在 Nashorn 中的特定上下文中执行函数

C 编程 - 关于花括号的困惑

c# - Rx 如何将命令与另一个可观察对象结合起来

c# - 打开在 C# 中创建的 OpenXML Word 文档时未应用图像大小

c# - WPF MVVM,我应该把 View 的特定属性放在哪里?