Simple Delegate (Delegate) VS. Multicast Delegates

Simple Delegate (delegate) vs. Multicast delegates

Delegates in .NET are multicast delegates. Regardless of whether you choose to attach zero or one or several handlers to them, they are still multicast delegates.

This article explains it pretty well:

delegate void Del(string s);

class TestClass
{
static void Hello(string s)
{
System.Console.WriteLine(" Hello, {0}!", s);
}

static void Goodbye(string s)
{
System.Console.WriteLine(" Goodbye, {0}!", s);
}

static void Main()
{
Del a, b, c, d;

// Create the delegate object a that references
// the method Hello:
a = Hello;

// Create the delegate object b that references
// the method Goodbye:
b = Goodbye;

// The two delegates, a and b, are composed to form c:
c = a + b;

// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
d = c - a;

System.Console.WriteLine("Invoking delegate a:");
a("A");
System.Console.WriteLine("Invoking delegate b:");
b("B");
System.Console.WriteLine("Invoking delegate c:");
c("C");
System.Console.WriteLine("Invoking delegate d:");
d("D");
}
}
/* Output:
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
*/

Difference between multicast delegate and simple delegate?

If delegate A point to method B and method C through multiple casting, why can't we have delegate A pointing to method B and method B calling method C?

Sure, you can do that. But the entire point of delegates is that the delegate consumer doesn't need to know what the implementation is. And in delegates with multiple targets, the key point is that they don't need to know about each-other. Since events are implemented by delegates, it is common for an event to have multiple subscribers, which is perhaps the main usage of delegates with multiple targets.

However, in .NET all delegates support multiple targets, so it is rather moot.

As an aside; in your A/B/C scenario, you could also do:

SomeDelegateType instance = delegate {
B();
C();
};

which is a single delegate that calls B and C. Or you can do:

SomeDelegateType instance = new SomeDelegateType(B) + new SomeDelegateType(C);

or whatever you want, really. It doesn't matter hugely.

.NET single vs. multicast delegates

Not really. All .NET delegates are derived from MulticastDelegate. When .NET was first written, there was originally a difference between single & multicast, but that distinction was dropped before release. However, the underlying types weren't merged into one.

You can't derive from Delegate directly in C#. You might be able to in raw IL, but there's not really much point, as a MulticastDelegate operates like a singlecast delegate to all intents and purposes.

Multicast Delegate Ambigous

When you have a delegate that has multiple handlers attached to it, you will still get only one return value. There is no direct way to get the other values and naturally you cannot chain the handler functions in a way that the return value of one would be sent to another. The only thing you will get is the last attached handler's return value is returned.

There is no ambiguous behaviour here really, it's just the way it works. If you want to chain the functions you have to use a different approach then a delegate. In this example you could just call the functions and that's it.

Is multicast delegate create new reference for each chaining?

Delegates are immutable....

When you add a new handler a new delegate is created.

Under the hood it calls the Delegate.Combine Method

Concatenates the invocation lists of two delegates.

Returns

A new delegate with an invocation list that concatenates the
invocation lists of a and b in that order
. Returns a if b is null,
returns b if a is a null reference, and returns a null reference if
both a and b are null references.

You can see it in action here

Action action = <>c.<>9__0_0 ?? (<>c.<>9__0_0 = new Action(<>c.<>9.<M>b__0_0));
Action action2 = action;
action = (Action)Delegate.Combine(action, <>c.<>9__0_1 ?? (<>c.<>9__0_1 = new Action(<>c.<>9.<M>b__0_1)));
action2();
Console.ReadKey();

Multicast delegate C#

Yes, it's an example of a multicast delegate. Note that instead of

new MyDelegate(AddNumbers)

you can typically say just

AddNumbers

because a so-called method group conversion exists that will create the delegate instance for you.

Another thing to note is that your declaration public delegate void MyDelegate(int a, int b); does not have to reside inside another type (here inside the MainPage class). It could be a direct member of the namespace (since it's a type). But of course it's perfectly valid to "nest" it inside a class, as you do, for reasons similar to the reason why you create nested classes.

MultiCast delegates in c#

Is there any relationship between events and multicast delegates?

In C# every delegate declaration will generate a multicast delegate. And events are actually two methods internally, called add and remove accessors with a delegate parameter. They meant to add/remove subscribers (practically change an underlying multicast delegate instance).

Do we have any practical scenarios where all the methods need to be executed but only the last method value should be returned like what the multicast delegate does?

No, this should be actually avoided. That's why there aren't not non-void events in the framework. When using public events we can assume that they have more than one subscribers.

I will not repeat an earlier answer of mine for a similar question (how to return the result of every subscriber) but it also may worth checking: How to use string delegate subscribed to 2 methods

On the other hand, when delegate instances are just used as callbacks (eg. method parameters) they are often non-void ones (such as the Func<...> delegate family). Though technically they are also multicast delegates it is not expected that they have multiple targets. These are often instantiated by some lambda expression (() => DoSomething()) in which case they always have only a single target.

Why this multicast delegation isn’t working with functions in C#?

According to the spec:

If the delegate invocation includes output parameters or a return value, their final value will come from the invocation of the last delegate in the list.

If you need more control over individual results, then use GetInvocationList():

foreach (MyDlgt myDlgt in MultiCast.GetInvocationList())
{
double result = myDlgt(NUM1, NUM2);
}


Related Topics



Leave a reply



Submit