从KeyValuePair获取密钥参考

时间:2013-03-03 23:06:12

标签: c#-4.0 dictionary keyvaluepair

我有以下课程。

public class myType
{
  public event Action myAction;
}

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

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

在我的主要内容中我有一个带签名的方法 void SomeMethod(myType,Dictionary)

通过以下循环,我添加了对象的行为:

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

运行此循环后,当调用其中一个对象的操作时,效果就好像循环使用了字典中的最后一对.Key来表示所有lambda表达式。

另一方面,循环中的变化很小:

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

运行此循环后,所有对象操作都按预期工作。

我有点不知道为什么这样的改变会产生这样的影响。 keyvaluepair可以是一个struct,键本身就是一个引用类型(我的类的一个实例)。任何想法为什么这样做?

提前感谢任何建议。

1 个答案:

答案 0 :(得分:1)

  

运行此循环后,当我的一个对象的动作是   调用,效果好像循环使用了最后一对。键入   所有lambda表达式的字典。

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

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

(第一个代码也有一个闭包,但这只是变量在当前作用域中存活,事件处理程序共享相同的闭包。)