Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在foreach循环中总是使用相同的值调用事件处理程序_C#_User Interface_Lambda_Callback - Fatal编程技术网

C# 在foreach循环中总是使用相同的值调用事件处理程序

C# 在foreach循环中总是使用相同的值调用事件处理程序,c#,user-interface,lambda,callback,C#,User Interface,Lambda,Callback,我想将一组回调函数绑定到C#中的GUI元素,每个元素用不同的参数调用相同的处理函数 指定的道路 # Assign element #1 to widget widget.Click += () => {ProcessClick(1) ;} ; # Assign element #2 to widget widget.Click += () => {ProcessClick(2) ;} ; ... 这似乎是多余的。然而,一个天真的循环 Widget widget ; for

我想将一组回调函数绑定到C#中的GUI元素,每个元素用不同的参数调用相同的处理函数

指定的道路

# Assign element #1 to widget

widget.Click += () => {ProcessClick(1) ;} ;

# Assign element #2 to widget

widget.Click += () => {ProcessClick(2) ;} ;

...
这似乎是多余的。然而,一个天真的循环

Widget widget ;

foreach (int i in new List<int>() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} )
{
    # Assign element i to widget

    widget.Click += () => {ProcessClick(i) ;} ;
}
Widget;
foreach(新列表中的int i(){0,1,2,3,4,5,6,7,8,9})
{
#将元素i分配给小部件
widget.Click+=()=>{ProcessClick(i);};
}
将不起作用,因为一旦调用任何回调,循环将过期,导致每个小部件调用
ProcessClick(9)

我觉得应该有一个简单的解决办法,但我被卡住了


如何将回调函数绑定到GUI元素(每个元素使用不同的参数调用函数),而不将它们全部拼写出来?

I
在循环过程中由代理捕获。您需要将其值复制到循环中的局部变量以使其工作:

Widget widget ;

foreach (int i in new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } )
{
    # Assign element i to widget

    int index = i;
    widget.Click += () => {ProcessClick(index) ;} ;
}
Widget;
foreach(新列表中的int i(){0,1,2,3,4,5,6,7,8,9})
{
#将元素i分配给小部件
int指数=i;
widget.Click+=()=>{ProcessClick(index);};
}

有关变量捕获的更多信息,请参见。在后者中,您还可以找到有关C#团队在C#5中所做的突破性更改的信息,对于这些更改,变量在逻辑上位于循环内部(如DavidG所述)

i
由您的代表在循环过程中捕获。您需要将其值复制到循环中的局部变量以使其工作:

Widget widget ;

foreach (int i in new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } )
{
    # Assign element i to widget

    int index = i;
    widget.Click += () => {ProcessClick(index) ;} ;
}
Widget;
foreach(新列表中的int i(){0,1,2,3,4,5,6,7,8,9})
{
#将元素i分配给小部件
int指数=i;
widget.Click+=()=>{ProcessClick(index);};
}

有关变量捕获的更多信息,请参见。在后者中,您还可以找到有关C#团队在C#5中所做的突破性更改的信息,对于这些更改,变量在逻辑上位于循环内部(如DavidG所述)

Eric Lippert关于这个主题的很多有用的东西Eric Lippert关于这个主题的很多有用的东西值得注意的是这在C#version 5中被改变了,现在每次闭包都会关闭变量的一个新副本。事实上,我没有注意到的是,
int index
创建了一个不同的
index
实例,每个lambda函数都可以分别引用该实例。谢谢@fbmd正如DavidG所写,C#5中的循环变量是循环块的内部变量,不再像Eric Lippert在这里解释的那样被捕获:值得注意的是,这在C#版本5中发生了更改,现在每次闭包都会关闭变量的一个新副本。事实上,我没有注意到的是,
int index
创建了一个不同的
index
实例,每个lambda函数都可以分别引用该实例。谢谢@fbmd正如DavidG所写,C#5中的循环变量是循环块的内部变量,不再被捕获,正如Eric Lippert在这里所解释的: