katie77
katie77

Reputation: 1813

Clarification about delegates

What is the below code doing? I think the pointer will be changed to the multiply method. But what is "+=" doing here. I am confused.

    delegate int calc(int a , int b);

    static void Main(string[] args)
    {
        calc c = new calc(Add);
        c += new calc(Multiply);
        Console.WriteLine(c(3, c(4, 2)));
        Console.Read();
    }

    public static int Add(int a, int b)
    {
        return (a + b);
    }

    public static int Multiply(int a, int b)
    {
        return (a * b);
    }

Upvotes: 3

Views: 134

Answers (4)

Enigmativity
Enigmativity

Reputation: 117019

You can think of delegates as a cross between value types (like int or double) and arrays of method addresses.

You know that if you write this code:

var x = 5;
var y = x + 2;
y += 3;

Then afterwards x == 5 & y == 10 even though y had an intermediate value of 7 this was "thrown away" when the final assignment occurred.

Quite clearly the final value of y isn't 3.

In your code you wrote this:

calc c = new calc(Add);
c += new calc(Multiply);

As with y, the final value of c isn't Multiply. It's really more like this:

c == { Add, Multiply }

When you then call something like c(4, 2) you are effectively calling both Add & Multiply and because the delegate returns a value you only get back the final delegate's value - in this case from Multiply - and that's what makes it appear that the "pointer" changed to the Multiply method.

You could try adding in this code before you call c:

c -= new calc(Multiply);

and this will effectively return c back to this:

c == { Add }

And this is why delegates appear to behave like arrays of method addresses.

Now if you change your Add & Multiply methods to look like this:

public static int Add(int a, int b)
{
    Console.WriteLine("Add({0}, {1})", a, b);
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("Multiply({0}, {1})", a, b);
    return (a * b);
}

you can then watch the calls as they occur. Your original code runs like this:

Add(4, 2)
Multiply(4, 2)
Add(3, 8)
Multiply(3, 8)
24

I hope this helps.

Upvotes: 0

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59101

The + and += operator

Similar to how you use the + operator to add values, you can use the += operator to both add and assign back to the same value.

An example of these operators applied to ints:

int a = 5;
a += 7; // a is now 12
a = a + 11;
Console.WriteLine(a);

24

Combining delegates

As AVD mentioned, you use the + and += operators to combine delegates.

When you apply these operators to delegates, you aren't doing a mathematical "sum" or "sum and assign", like my example with ints. Instead you are modifying a list of methods to be called when you invoke the delegate.

From that article:

Delegates can be combined such that when you call the delegate, a whole list of methods are called - potentially with different targets

So when you add/combine delegates, you'll end up calling multiple methods.

If you change your code to:

public static int Add(int a, int b)
{
    Console.WriteLine("From Add");
    return (a + b);
}

public static int Multiply(int a, int b)
{
    Console.WriteLine("From Multiply");
    return (a * b);
}

Then you will see this output when you run the program:

From Add
From Multiply
From Add
From Multiply
24

This is because:

  • You combined the Add and Multiply delegates, so both get called when you call c(x, y)
  • Multiply is the last delegate you added to that chain of delegates
  • You are calling c(x, y) twice. This is similar to if you had called: Multiply(3, Multiply(4, 2))

Return values from combined delegates

That point about the last delegate you added to the chain is also mentioned in the article:

If a delegate type is declared to return a value (i.e. it's not declared with a void return type) and a combined delegate instance is called, the value returned from that call is the one returned by the last simple delegate in the list.

The last method you added to the chain was Multiply, so all other return values are thrown out, and only the return value from Multiply is used when you call c(x, y).

You can see this demonstrated in your program. 3 * 4 * 2 is 24, which is your program's output. None of your calls to Add impact the final result.

Upvotes: 4

KV Prajapati
KV Prajapati

Reputation: 94625

Its called Combining the delegates.

Upvotes: 0

Zenwalker
Zenwalker

Reputation: 1919

+= is like appending multiple calls to the delegate object. Since its a multicast delegates, you can append multiple destination calls to the a single delegate. To append to a delegate, you need new delegate objects. And thats whats been doing in the second line.

Its similar to,

CalcDelegate C1, C2;
C1 = new CalcDelegate(Add);
C2 = new CalcDelegate(Multiply);
C1 = C1 + C2;

Upvotes: 2

Related Questions