I was reading a book illustrated C # 2012 in the section Combining Delegates point not notice that? Purpose of the delegates are immutable.
Combining Delegates All the delegates you’ve seen so far have had only a single method in their invocation lists. Delegates can be “combined” by using the addition operator. The result of the operation is the creation of a new delegate, with an invocation list that is the concatenation of copies of the invocation lists of the two operand delegates. For example, the following code creates three delegates. The third delegate is created from the combination of the first two.
MyDel delA = myInstObj.MyM1;
MyDel delB = SClass.OtherM2;
MyDel delC = delA + delB; // Has combined invocation list
Although the term combining delegates might give the impression that the operand delegates are modified, they are not changed at all. In fact, delegates are immutable. After a delegate object is created, it cannot be changed. Figure 15-6 illustrates the results of the preceding code. Notice that the operand delegates remain unchanged.
Delegates are pointers to a method, either concrete or anonymous (well, even anonymous methods are compiled with some compiler-generated identifier).
Would be reasonable that something that points to some concrete thing be mutable? I don't think so. Each instance represents a pointer to some method. Do you want to point to some other method? Create a new pointer. That is, you instantiate a new delegate.
In the other hand, the addition of two or more delegates has this result because
+
operator can be overloaded. That is, delegates can be part of an addition but internally+
's overload is creating a new delegate with an invocation list.Thread-safety and speed are the primary concerns here. A delegate update is not atomic, it requires updating 6 fields and a list. Making it atomic so it cannot get corrupted requires a lock, far too expensive for such a basic operation that rarely needs to be thread-safe.
By making it immutable, the delegate object cannot get corrupted since it always sets fields on an object that nobody has a reference to yet. Reassigning the delegate object reference is atomic, a basic .NET memory model guarantee. So no need for a lock anymore. The trade-off is less efficient memory use, it is a small penalty.
Do keep in mind that the thread-safe delegate update does not automatically make your code thread-safe as well. The test-and-fire code needs to copy the reference to avoid NRE and you can make a callback to a method that was already unsubscribed.