Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Multicast Delegate to chain functions

Tags:

c#

delegates

My question is detailed in the following code - the reason I'm asking this is that I'm experimenting with delegates:

//create the delegate          
delegate int del(int x);

class Program {


    static void Main(string[] args) {

        Program p;
        p = new Program();

        del d = p.a;
        d += p.b;
        d += p.c;
        d += p.d;
        d += p.e;
        Console.WriteLine(d(10)); //<<was hoping it would be 10+2+3+4+5+6

        Console.WriteLine("press [enter] to exit");
        Console.ReadLine();
    }

    private int a(int x) { Console.WriteLine("a is called"); return x + 2; }
    private int b(int x) { Console.WriteLine("b is called"); return x + 3; }
    private int c(int x) { Console.WriteLine("c is called"); return x + 4; }
    private int d(int x) { Console.WriteLine("d is called"); return x + 5; }
    private int e(int x) { Console.WriteLine("e is called"); return x + 6; }

} 

16 is returned....

enter image description here

All the functions fire, as the various messages "a is called" etc all get printed to the console but only the amount returned from the last function e is returned - I'm assuming in the background they are getting returned but then overwritten?

like image 942
whytheq Avatar asked Mar 05 '13 15:03

whytheq


People also ask

What is a multicast delegate how might it be used?

The multicast delegate contains a list of the assigned delegates. When the multicast delegate is called, it invokes the delegates in the list, in order. Only delegates of the same type can be combined. The - operator can be used to remove a component delegate from a multicast delegate.

Can delegates be chained together C#?

Delegates can be chained together; for example, multiple methods can be called on a single event. Methods don't have to match the delegate type exactly.

What is the difference between events and multicast delegates?

Delegates are pointer to functions and used for call back. Multicast delegates help to invoke multiple callbacks. Events encapsulate delegate and implement publisher and subscriber model.

When multicast delegate is invoked the methods in the list are called in synchronous order?

A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear.


2 Answers

When you have a multicast delegate like d in your question, the return value is the return value from the last method of the invocation list of d.

In general, for multicast delegates, it is most natural to use return type void.

The compiler had no chance to guess that you were hoping for 10+2+3+4+5+6. You didn't specify it anywhere.

You could change your delegate type into:

delegate void del(int xToAdd, ref int sum);

Then your method a, for example, should look like this:

private void a(int x, ref int sum) { Console.WriteLine("a is called"); sum += x + 2; }

The multicast delegate instance d would then be called like this:

int sum = 0;
d(10, ref sum);
Console.WriteLine(sum);

I hope this helps.

like image 143
Jeppe Stig Nielsen Avatar answered Nov 15 '22 15:11

Jeppe Stig Nielsen


That's not how return types are handled for delegates. What will happen is that all of the handlers will be executed independently of each other, and then one will be chosen at random (technically it's the handler that was subscribed last, but you shouldn't rely on that) to be returned to the caller that invoked the delegate.

I would highly discourage you from ever using an event (you are treating this delegate as if it's an event) that has a return value. The behavior is virtually never desirable. If you want a return value it makes sense to ensure that your delegate is always mapped to exactly one function, no more, no less.

As for actually generating the desired result, while there are a number of approaches, you would be better served with a more traditional collection of delegates:

List<Func<int, int>> functions = new List<Func<int, int>>();
//populate

int result = functions.Aggregate(10, (total, func) => func(total));
like image 25
Servy Avatar answered Nov 15 '22 15:11

Servy