6

What happens when I add a method to existing delegate? I mean when I added the method1 to del, del holds the address of method1. When I add method2 afterwards, del still points to Method1 and Method 2 address is inserted on the bottom of it. Doesn't this mean I changed the delegate? If I can change this why in the books it is told "delegates are immutable" ?

MyDel del = method1; 
del += method2; 
del += method3;
Lyrk
  • 1,936
  • 4
  • 26
  • 48

4 Answers4

8

You're not changing the Delegate object - you're changing del to refer to a different object.

It's exactly the same as with strings. Let's convert your code into the same thing but with strings:

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

You end up with str referring to a string object with contents "xyz". But you haven't modified the string objects with contents "x", "y" or "z".

So it is with delegates.

del += method2;

is equivalent to:

del = del + method2;

which is equivalent to:

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

In other words, "create a new delegate object which has invocation lists referring to the existing two delegate objects". (If either del or method2 is null, it doesn't need to create a new object.)

See Delegate.Combine for more details.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • In your example, str was holding the address of object that holds "x" at first. At the end, str is holding the address of the object that holds "xyz". The address stored in str variable is changed. Doesn't this mean I changed str? If not, change means different thing in programming? – Lyrk Nov 08 '16 at 09:19
  • @Lyrk: The value of `str` changes, so that it refers to a different string object. After all, you're performing an *assignment* - you're *setting the value of the variable*. Does it make things simpler for you if you consider it as `str = str + "y"`? What do you think the expression `str + "y"` refers to? Perhaps you need to read http://jonskeet.uk/csharp/references.html It's really important to distinguish between the value of the varlable (which is a reference) and the object itself. Changing the value of the variable doesn't modify the object. – Jon Skeet Nov 08 '16 at 09:22
5

Let me use a simple analogy. int is immutable, so when you put

int x = 123;
x += 1;

it actually means

int _x = x + 1;
x = _x;

when adding one you get a new temporary variable _x and then drop initial x by substituting it with _x; in case of delegates

del += method2; 

means quite the same:

delegate _del = delegate.Combine(del, method2);
del = (MyDel) _del;
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
3
del += method2;

The compiler turns this into something like:

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

As you can see, a new delegate is derived from the original and additional one (both of which remain unchanged), then the result is re-assigned to the original delegate variable. (It is only the delegate object itself that is immutable, not the variable/field referencing it.)

Related question: How does the + operator work for combining delegates?

Community
  • 1
  • 1
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
3

And another version in other words:

MyDelegate delegateOriginal = Method1;
MyDelegate copyOfOriginal = delegateOriginal;


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

Return true above because variables delegateOriginal and copyOfOriginal reference to the same instance.

Then

delegateOriginal += Method2;

If delegate was mutable next expression then will return true, because variables will reference same object, But:

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

Because delegate is immutable.
Line delegateOriginal += Method2; will create new instance of delegate and put it reference to the original variable.

Fabio
  • 31,528
  • 4
  • 33
  • 72