0

Delegate are reference type but still when trying to pass it to a method it requires a ref keyword.

This reminds me of string that requires ref to be modified within a method because they are immutable, are delegate immutable?

Here is my mini project:

delegate void MyDel();
static void Main(string[] args)
{
    MyDel _del  = new MyDel(Idle);

    while(true)
    {
        if(_del != null)
            _del();  
            int c = Console.Read();
            AI(c,ref _del);
            Console.Read();
            Console.Read();
        }
    }
}
    static void AI(int c, ref MyDel del) 
    {
        if(c == 'a')
        {
            del = Attack;
        }else if(c == 'i'){
            del = Idle;
        }else if (c == 's'){
            del = SwingSword;
        }
        else if (c == 'w')
        {
            del = Attack;
            del += SwingSword;
        }
        else {
            del = Idle;
        }
    }

Without the ref keyword I am back to the swap method case where things happen only inside the method.

Can anyone tell me why delegates need to be passed by reference?

Everts
  • 10,408
  • 2
  • 34
  • 45

2 Answers2

4

The reason you have to use ref is because you are changing the delegate that _del refers to.

Change your code to the following and you won't need the ref parameter:

static MyDel AI(int c) 
{
    if(c == 'a')
    {
        return Attack;
    }
    if(c == 'i')
    {
        return Idle;
    }
    if (c == 's')
    {
        return SwingSword;
    }
    if (c == 'w')
    {
        return (MyDel)Attack + SwingSword;
    }
    return Idle;
}

C# does not pass by reference unless you specify the ref keyword. However, since the value of a variable of a delegate type is a reference to a method, the value passed is a reference. Use the ref keyword and you pass a reference to the variable's store, not the method, thus it becomes possible to change its value.

If the previous paragraph is as clear as mud, take a read of https://stackoverflow.com/a/8708674/7122, which is a very good explanation of pass by value vs pass by reference.

Community
  • 1
  • 1
David Arno
  • 42,717
  • 16
  • 86
  • 131
  • Ok That is what I had in the first place but did not know about the possibility to use Attack + SwingSword. And your explanation makes sense, at least to me. – Everts Nov 06 '13 at 13:26
  • Is there any reason why return Attack+ SwingSword; shows as error in VS? I fixed it declaring a new delegate and assigning both method but what you show seems wrong. – Everts Nov 06 '13 at 13:34
  • @fafase Apologies, I should have checked the code before posting. It needs a cast so that it knows it's adding a MyDel to a MyDel, rather than just any old method group to another. Code updated. – David Arno Nov 06 '13 at 13:40
  • 1
    Indeed :), now we are friends again. Thanks for it all. – Everts Nov 06 '13 at 13:41
3

This is not about immutability. You are assigning a new value to a variable declared in an outer scope, and you want the outer scope to be aware of this assignment - that's why you need ref.

This would be true for any type.

*Edit

"Outer scope" is not actually the best term. "The calling method's scope" is what I meant.

dcastro
  • 66,540
  • 21
  • 145
  • 155