向现有委托添加方法时会发生什么?我的意思是当我将method1添加到del时,del保存了method1的地址。当我之后添加method2时,del仍指向Method1,方法2地址插入其底部。这是不是意味着我改变了代表?如果我可以改变这一点,为什么在书中告诉“代表是不可改变的”?
MyDel del = method1;
del += method2;
del += method3;
答案 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);
换句话说,"创建一个新的委托对象,该对象具有引用现有两个委托对象的调用列表"。 (如果del
或method2
为空,则不需要创建新对象。)
有关详细信息,请参阅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);
如您所见,新委托派生自原始委托和另外委托(两者都保持不变),然后将结果重新分配给原始委托变量。 (只有委托对象本身是不可变的,而不是引用它的变量/字段。)
答案 3 :(得分:2)
换句话说是另一个版本:
MyDelegate delegateOriginal = Method1;
MyDelegate copyOfOriginal = delegateOriginal;
Object.ReferenceEquals(printAllhandler, anotherHandler); // return true
上面返回true,因为变量delegateOriginal
和copyOfOriginal
引用同一个实例。
然后
delegateOriginal += Method2;
如果delegate
是可变的,则下一个表达式将返回true,因为变量将引用相同的对象,但是:
Object.ReferenceEquals(printAllhandler, anotherHandler); // return false
因为delegate
是不可变的
第delegateOriginal += Method2;
行将创建一个新的委托实例,并将其引用到原始变量。