8

This is a followup question to this other question.

Background

Working from the MSDN Delegates Tutorial (C#), I see the following:

Note that once a delegate is created, the method it is associated with never changes — delegate objects are immutable.

And then, in the code sample, I see this (Spread out a little througout the code):

public delegate void ProcessBookDelegate(Book book);

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));

The Question

Now obviously, the way the code is written here a new delegate is created for each process. I am guessing the immutability is relevant if you try to do stuff like

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);
ProcessBookDelegate thisIsATest = new ProcessBookDelegate(totaller.AddBookToTotal);

which should... still compile when thisIsATest is immutable? So what problem has Microsoft solved by making it immutable? What problems would we run into if C# 6 made delegates mutable?

EDIT

I believe the immutability will prevent this:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest.ChangeTheDelegateInABadFashion();

someFunction(thisIsATest); //This function works as normal
                           //because the delegate is unchanged
                           //due to immutability

but the immutability will NOT prevent this:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);

thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());

someFunction(thisIsATest); //This function works weird now because
                           //it expected the unchanged delegate

Am I correct in this understanding?

15

I think you're mixing up what immutability means.

What Immutability Isn't

Take a look at this example:

string s = "Hello";
s = "World";

Are strings immutable? Yes.
Will this compile? Yes.
Have we in any way changed the string instance? No.

We are not making any changes to "Hello". We are creating a string, assigning it to the variable s, then we are creating a new string, and overwriting the variable s with this new string. Immutability does not play a part here.

What Immutability Is

If we were to try something like this:

s.MutateInSomeWay();

where MutateInSomeWay is a method which changes the string "Hello" (the value of s) itself, that would not be valid due to string immutability.

Any methods of string which change it in any way are not really changing it, they are creating a new string with the changed value and returning it to the caller.

but the immutability will NOT prevent this:

ProcessBookDelegate thisIsATest = new ProcessBookDelegate(PrintTitle);  
thisIsATest = new ProcessBookDelegate(ChangeTheDelegateInABadFashion());
someFunction(thisIsATest); //This function works weird now because
//it expected the unchanged delegate

Am I correct in this understanding?

Yes, immutability will not prevent it because it's perfectly valid, you have not mutated any object. Of course, you are not entirely clear on what is ChangeTheDelegateInABadFashion(), so it's hard to be specific.

  • 1
    It's worthwhile to note that the only aspect of a delegate that are immutable are the method that will be invoked, and the identity of its target. The target object itself will often be mutable (indeed the whole purpose of many delegates is to mutate the target object!), and even if the delegate holds the only reference to a target object it would be entirely legitimate for a Func<int> to return 1 the first time it's called, 2 the second, etc.--this behaving essentially like a mutable object. – supercat Jan 18 '14 at 17:21
  • Immutability comes in when you try to modify string like this. s[2] = 't'. – M.kazem Akhgary Jan 3 '16 at 17:09
  • As someone just picking up C#, I wish I could share @supercat's answer here directly with others. It makes no sense to me to call delegates immutable given the fact that they may contain arbitrary code that can have whatever mutations it wants, visible from outside the delegate. – trptcolin Mar 16 '17 at 2:49
4

Reasons in short:

  • An immutable object can be in exactly one state, the state in which it was created (security)
  • Are thread safe can be used freely
  • Memory optimization
  • Performance is better

Check out these two questions on Stack Overflow for more info:

2

standard thread safety I believe; if you know a delegate will never change then you can make some assumptions about it

in particular you can be assured that a evil piece of code can't change the delegate you are passing to several functions (even by accident)

this could cause hard to trace bugs and leave the programmer wondering why his delegate wasn't called

  • Since delegates can be bound to mutable objects, there's no reason to expect that repeated calls to the same delegate will do the same thing. You're right about the thread-safety point, though: the purpose of making delegates immutable is to ensure that they are always bound to a method which is compatible with the type of the attached instance. If the method and instance could change separately, bad things could happen. – supercat Dec 21 '13 at 8:43
2

The simple answer is mutating a delegate makes very little sense. A delegate is very much a reference to a function, a set of executing code. Mutating that suggests that you are mutating that function.

Ask yourself, what would that method on a delegate look like, and what would do? In a sense, it would be rewriting the code of that function. That opens an enormous (almost intractable) amount of complexity to the C# specification and compiler implementations for very little benefit with large performance costs. Hence the restriction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.