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
Getmanifestresourcestream Returns Null
How to Clear Cookies Using ASP.NET MVC 3 and C#
Convert Transparent Png to Jpg with Non-Black Background Color
Build Visual Studio Project Through the Command Line
What's the Difference Setting Embed Interop Types True and False in Visual Studio
Translate Perl Regular Expressions to .Net
Can Structs Contain Fields of Reference Types
Check If All Items Are the Same in a List
ASP.NET MVC: Calling a Method from a View
Changing the Cursor in Wpf Sometimes Works, Sometimes Doesn'T
Post-Increment Within a Self-Assignment
How to Embed My Own Fonts in a Winforms App
How to Generate Truly (Not Pseudo) Random Numbers with C#
Visual Studio 2010 Conditional References
Inheriting Comments from an Interface in an Implementing Class