我正在阅读C#2012中的一本书,在“结合代表”一节中没有注意到这一点?代表的目的是不可改变的。
组合代表 到目前为止,你见过的所有代表都只有 调用列表中的单个方法。代表们可以“合并” 通过使用加法运算符。操作的结果是 创建一个新的委托,其中包含一个调用列表 两个操作数的调用列表的副本的串联 与会代表。例如,以下代码创建三个委托。 第三个代表是由前两个代表组合而成的。
MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;
MyDel delC = delA + delB; // Has combined invocation list
虽然组合代表这一术语可能给人的印象是 操作数委托被修改,它们根本没有改变。在 事实上,代表是不可改变的。创建委托对象后,它 无法改变。图15-6说明了结果 前面的代码。请注意,操作数委托保持不变。
答案 0 :(得分:7)
线程安全性和速度是这里的主要关注点。委托更新不是原子的,它需要更新6个字段和列表。使其成为原子以便它不会被破坏需要一个锁,这对于很少需要的线程安全的基本操作来说太昂贵了。
通过使其成为不可变的,委托对象不会被破坏,因为它总是在没有人引用的对象上设置字段。重新分配委托对象引用是原子的,基本的.NET内存模型保证。所以不再需要锁了。权衡是内存使用效率较低,这是一个小小的惩罚。
请记住,线程安全的委托更新不会自动使您的代码也是线程安全的。 test-and-fire代码需要复制引用以避免NRE,并且您可以回调已经取消订阅的方法。
答案 1 :(得分:2)
委托是指向某个方法的指针,无论是具体的还是匿名的(,甚至匿名方法都是使用一些编译器生成的标识符编译的。)
指出某些具体事情是可变的是合理的吗?我不这么认为。每个实例代表一个指向某个方法的指针。你想指出其他一些方法吗?创建一个新指针。也就是说,您实例化一个新的委托。
另一方面,添加两个或更多代表的结果是+
operator can be overloaded。也就是说,委托可以成为添加的一部分,但内部+
的重载正在创建一个带有调用列表的新委托。