2013-03-03 48 views
0

我有以下类。从KeyValuePair获取重要参考

public class myType 
{ 
    public event Action myAction; 
} 

以及包含该类的一些实例的字典。

var myDictionary = new Dictionary<myType, string>(); 

在我主我有签名 无效的someMethod的方法(的myType,字典)

用下面的循环添加我的对象的行为:

foreach(var pair in myDictionary) 
    pair.Key.myAction +=() => SomeMethod(pair.Key, myDictionary); 

运行该循环之后,当我的一个对象的动作被调用时,效果就好像循环已经使用了字典中所有lambda表达式的最后一个pair.Key。

在另一方面与环中的小变化:

foreach(var pair in myDictionary) 
{ 
    myType temp = pair.Key; 
    pair.Key.myAction +=() => SomeMethod(temp, myDictionary); 
} 

运行该循环后,所有对象的动作正常工作。

我有点茫然,为什么这样的改变会产生这样的效果。 keyvaluepair可能是一个结构体,通过键本身就是一个引用类型(我的类的一个实例)。任何想法为什么这样表现?

在此先感谢您的任何建议。

回答

1

运行该循环后,当我的对象之一的作用是 调用,其效果是如果循环使用过的最后一个pair.Key在 字典中所有的lambda表达式。

是的,这正是发生了什么事情。您有一个由所有事件处理程序使用的变量pair。循环后,变量包含循环中最后一项的键。

通过在作用域中创建局部变量并在lambda表达式中使用它,实际上是为每个事件处理程序创建一个闭包。本地变量不是作为常规本地变量存储在堆栈中的,而是在闭包中,并且由于每个事件处理程序都有自己的闭包,因此每个事件处理程序都会得到一个局部变量版本。

(没有与第一代码也封闭,但是这仅仅是变量生存的电流范围,事件处理程序共享相同的关闭。)

+0

感谢您在清除了。 – 2013-03-04 10:01:13