代表是不变的,但如何?

时间:2016-11-08 09:06:03

标签: c# delegates

向现有委托添加方法时会发生什么?我的意思是当我将method1添加到del时,del保存了method1的地址。当我之后添加method2时,del仍指向Method1,方法2地址插入其底部。这是不是意味着我改变了代表?如果我可以改变这一点,为什么在书中告诉“代表是不可改变的”?

MyDel del = method1; 
del += method2; 
del += method3;

4 个答案:

答案 0 :(得分:8)

您没有更改Delegate对象 - 您正在更改del以引用其他对象。

与字符串完全相同。让我们将您的代码转换为相同的东西,但使用字符串:

string str = "x";
str += "y";
str += "z";

最后,str引用内容为"xyz"的字符串对象。但是您还没有使用内容"x""y""z"修改字符串对象。

所以代表们也是如此。

del += method2;

相当于:

del = del + method2;

相当于:

del = (MyDel) Delegate.Combine(del, method2);

换句话说,"创建一个新的委托对象,该对象具有引用现有两个委托对象的调用列表"。 (如果delmethod2为空,则不需要创建新对象。)

有关详细信息,请参阅Delegate.Combine

答案 1 :(得分:5)

让我用一个简单的比喻。 int是不可变的,所以当你把

int x = 123;
x += 1;

实际上意味着

int _x = x + 1;
x = _x;

添加一个临时变量_x然后删除初始x 替换它与_x;如果是代表

del += method2; 

意思相同:

delegate _del = delegate.Combine(del, method2);
del = (MyDel) _del;

答案 2 :(得分:3)

del += method2;

编译器将其转换为:

del = (MyDel)Delegate.Combine(del, method2);

如您所见,新委托派生自原始委托和另外委托(两者都保持不变),然后将结果重新分配给原始委托变量。 (只有委托对象本身是不可变的,而不是引用它的变量/字段。)

  

相关问题: How does the + operator work for combining delegates?

答案 3 :(得分:2)

换句话说是另一个版本:

MyDelegate delegateOriginal = Method1;
MyDelegate copyOfOriginal = delegateOriginal;


Object.ReferenceEquals(printAllhandler, anotherHandler); // return true

上面返回true,因为变量delegateOriginalcopyOfOriginal引用同一个实例。

然后

delegateOriginal += Method2;

如果delegate是可变的,则下一个表达式将返回true,因为变量将引用相同的对象,但是:

Object.ReferenceEquals(printAllhandler, anotherHandler); // return false

因为delegate是不可变的 第delegateOriginal += Method2;行将创建一个新的委托实例,并将其引用到原始变量。