使用+ =更新操作在存储在集合或变量中后不会链接操作

时间:2017-04-10 22:57:32

标签: c# collections delegates action

我试图将Actions存储在这样的集合中:

List<Action> localActionList = new List<Action>();
localActionList.Add(anotherObject.action1);
localActionList.Add(anotherObject.action2);

稍后,我正在为此Action添加一个本地侦听器:

actionList[0] += LocalListenerMethod;

调用anotherObject.action1时,LocalListenerMethod不会触发。我已经到了我怀疑这与委托不变性有关的地步,但我无法想象如何做我需要做的事情(迭代一系列动作,将它们分配给一个本地监听器,在原始类中调用原始Action时调用。注意,简单地分配给原始Action时,我没有问题让侦听器触发。

更简单的样本(没有数组):

Action x = ()=> Console.WriteLine("a");
Action y = x;
x += ()=> Console.WriteLine("b");
x(); // prints "ab"
y(); // prints "a"

1 个答案:

答案 0 :(得分:0)

  

调用anotherObject.action1时,LocalListenerMethod无法启动

那是因为anotherObject.action1的价值从未改变过。

详细说明Eric的评论,请考虑:

string a = "A", b = "B";
List<string> list = new List<string>();

list.Add(a);
list.Add(b);
list[0] += "C";

虽然0的索引list中包含的元素现在具有值“AC”,但这并不意味着变量{{1}引用的string值}} 已经改变。怎么可能呢? a对象不知道该变量。变量list仍会引用字符串a

变量中的已传递给"A"方法,但这只涉及从变量中检索该值并将其发送到方法。变量本身只是一个临时存储位置,在需要之前保存该值。变量本身不会影响之后发生的任何事情。

同样,在您的示例中,语句

Add()

确实会更改actionList[0] += LocalListenerMethod; 的索引0处元素的值。但这对原始变量actionList的值没有任何影响。该变量的值保持原样。将该变量的传递给列表的anotherObject.action1方法只是将值(对委托类型实例的引用)从变量复制到方法的参数列表,因此可以传递。但是变量本身没有给列表,列表对象也没有任何方法来修改变量。

为了解决你的评论:

  

我将其更多地等同于Add()

这是非常不同的场景。这更像是这样的事情:

var x = new MyType() { prop1 = 5 }; var y = x; x.prop1 += 1;

请注意,在该示例中,代码修改list元素本身,而是修改list元素引用的对象的类成员。也就是说,表达式MyType x = new MyType { prop1 = 5 }; List<MyType> list = new List<MyType>(); list.Add(x); list[0].prop1 += 1; // Here, x.prop1 will be equal to 6, as would list[0].prop1 中的“变量”(即“更改的东西”)是list[0].prop1 += 1属性,而不是 prop1元素,就像上面的前两个例子一样。在第三个示例中,list[0]仅用于获取属性list[0]的对象,而不会参与prop1分配。


顺便说一句,埃里克的评论并不是很讽刺。他正在问你一些问题,这些问题旨在准确缩小让你对这个场景感到困惑的内容。他试图了解你对C#中其他场景的理解程度,以及他是否以及如何使用其他场景来帮助解释这个场景。在这次提问过程中,您可能已经发现了自己的误解,但如果没有,这些问题的答案将为Eric提供一种方法,可以专注于他需要关注的事情,以便对您做出有益的回应。尽可能高效。

提出问题是一项需要学习的技能。你可以通过在试图回答自己的问题的过程中对提出的问题变得不那么自卫来提高自己的提问技巧,特别是通过识别经典的教育技巧,经过时间考验并设计为使问答更有效率。