Simple Delegate (delegate) vs. Multicast delegates
Asked Answered
S

6

80

I have gone through many articles but I am still not clear about the difference between the normal delegates that we usually create and multicast delegates.

public delegate void MyMethodHandler(object sender);
MyMethodHandler handler = new MyMethodHandler(Method1);
handler += Method2;
handler(someObject);

The above delegate MyMethodHandler will call these two methods. Now where does multicast delegates come in. I have read that they can call multiple methods but I am afraid that my basic understanding about delegates is not correct.

Scintillate answered 3/2, 2010 at 13:38 Comment(0)
B
88

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!
*/
Blinders answered 3/2, 2010 at 13:40 Comment(6)
It's important to note that a multicast delegate will call its subscribers in an unpredictable order. DO NOT assume they will be called in any specific order.Kessler
@Scintillate If both (uni and multicase delegate) serving the same purpose, why we need both?Jarret
Is there any particular benefit to having delegates contain an invocation list, versus having multicast delegates's "Target" be an array of delegates and their "Method" be a static method which takes such an array as its first parameter?Homemaking
@MikeChristian got a link for "multicast delegate will call its subscribers in an unpredictable order"? The second paragraph of 15.3 seems to say it's called in order.Kopeisk
@MackieChan I believe that the "do not assume order" is for events, on the basis that the implementation of add and remove can be changed (see), even though the usual implementation is a MulticastDelegate.Soper
I don't see any satisfactory answer for single delegate and multicast delegate.Its seems like having one element in array is single value array and multiple value as multi value array!!.Slotnick
A
58

The C# specification states that all delegate types must be convertible to System.Delegate. In fact the way the implementation implements this is that all delegate types are derived from System.MulticastDelegate, which in turn derives from System.Delegate.

Is that clear? I'm not sure that answered your question.

Astra answered 3/2, 2010 at 15:57 Comment(1)
Yes Eric. Normally when I ask people(or people ask me) about delegates, we usually say there are two types of delegates-singlecast and multicast. Now I know that there is only one such things as a 'delegate' which can either be singlecast or multicast depending on the number of method references it contains.Scintillate
P
16

"All delegate instances have multicast capability." - http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx

"In C#, all delegate types support multicast" - http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx

Prefrontal answered 10/1, 2013 at 18:14 Comment(3)
How does any delegate instance have any capability to invoke any number of actions other than the number it was created to do? If a delegate was created to invoke three things, I would think that delegate instance will always do three things. Likewise, if it was created to do one thing. If a delegate was created to do exactly one thing, how can that instance ever do more?Homemaking
@supercat, its doesn't.Prefrontal
What then does "all delegate instances have multicast capability" mean? Certainly, all delegate types have such ability, and code which accepts a delegate for anything other than an event subscription must be prepared for it to be a multicast delegate (if an event uses multicast delegates internally, passing a multicast delegate to the Add method and later passing it to Remove might not actually unsubscribe the event; that the default event handlers malfunction in this way implies events aren't expected to be tolerant of multicast events).Homemaking
L
8

To clarify a bit: All delegates are instances of the class MulticastDelegate, regardless of whether they have one or multiple target methods. In principle there are no difference between a delegate with a single or multiple targets, although the runtime is optimized a bit towards the common case with a single target. (A delegate with 0 targets is not possible though, it is one or more.)

When you are instantiating a delegate like new MyMethodHandler(Method1), you create a delegate with a single target (the Method1 method).

Delegates with multiple targets are created by combining two existing delegates. The resulting delegate will have the sum of targets. Delegates can be combined explicitly with Delegate.Combine(), but also implicitly by using the += operator on an existing delegate, as in your example.

Invoking a delegate in turn calls every target in the delegate. So in your example handler(someObject); will call two methods (Method1 and Method2), since you have created a delegate with these two targets.

Linkage answered 3/7, 2015 at 10:44 Comment(0)
R
5

Sorry for adding to somebody else's answer but I thought that delegates are called in the order they are added.

"Multicast Delegates" section

http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx

Rafaello answered 21/8, 2013 at 8:45 Comment(1)
Yup, and returns the result of the last function if it has a return type - weird.Nano
R
-2

A multicast delegate is a delegate that has references to more than one function. When you invoke a multicast delegate, all the functions the delegate is pointing to, are invoked.

Type 1:

0 argument and void return type delegate -

Method 1 -

using System;

delegate void SampleDelegate ();    //A delegate with 0 argument and void     return type is declared

class MainClass
{
    public static void Main ()
    {
        SampleDelegate Del1 = new SampleDelegate (Message1);         //Del1 declared which points to function Message1
        SampleDelegate Del2 = new SampleDelegate (Message2);        //Del2 declared which points to function Message2
        SampleDelegate Del3 = new SampleDelegate (Message3);        //Del3 declared which points to function Message3
        SampleDelegate Del4 = Del1 + Del2 + Del3;                   //Del4 declared which points to function Message4

        //Del4 is then initialized as sum of Del1 + Del2 + Del3

        Del4 ();        //Del4 is invoked;

        //Del4 in turn invokes Del1, Del2 and Del3 in the same order they were initialized to Del4
        //Del1, Del2, Del3 in turn invokes their respective functions to which they point to
        //The three functions Message1, Message2 and Message3 gets executed one after another

    }

        //Output:
        //This is message 1
        //This is message 2
        //This is message 3

        Del4 - Del1;    //Removes Del1 from Del4
        Del4();           

        //New Output:
        //This is message 2
        //This is message 3

        Del4 + Del1;    //Again adds Del1 to Del4
        Del4();

        //New Output:
        //This is message 1
        //This is message 2
        //This is message 3


    public static void Message1 ()      //First sample function matching delegate signature
    {
        Console.WriteLine ("This is message 1");
    }

    public static void Message2 ()      //Second sample function
    {
         Console.WriteLine ("This is message 2");
    }

    public static void Message3 ()      //Third sample function
    {
        Console.WriteLine ("This is message 3");
    }
}

Method 2 -

using System;

delegate void SampleDelegate ();

class MainClass
{
    public static void Main ()
    {
        SampleDelegate del = new SampleDelegate (Message1);         //Declares del and initializes it to point to method Message1
        del += Message2;                                        //Now method Message2 also gets added to del. Del is now pointing to two methods, Message1 and Message2. So it is now a MultiCast Delegate
        del += Message3;                                        //Method Message3 now also gets added to del

        del ();                                                 //Del invokes Message1, Message2 and Message3 in the same order as they were added

        /*
        Output:
        This is Message1
        This is Message2
        This is Message3
        */

        del -= Message1;                                        //Method     Message1 is now removed from Del. It no longer points to Message1
                                                                //Del invokes the two remaining Methods Message1 and Message2 in the same order
        del ();
        /*
        New Output:
        This is Message2
        This is Message3
        */

        del += Message4;                                        //Method Message4 gets added to Del. The three Methods that Del oints to are in the order 1 -> Message2, 2 -> Message3, 3 -> Message4
                                                                //Del invokes the three methods in the same order in which they are present.
        del ();
        /*
        New Output:
        This is Message2
        This is Message3
        This is Message4
        */

    }

    public static void Message1 ()
    {
        Console.WriteLine ("This is Message1");
    }

    public static void Message2 ()
    {
        Console.WriteLine ("This is Message2");
    }

    public static void Message3 ()
    {
        Console.WriteLine ("This is Message3");
    }

    public static void Message4 ()
    {
        Console.WriteLine ("This is Message4");
    }
}

Type 2:

0 arguments and int return type delegate

Method 1-

using System;

delegate int SampleDelagate ();

class MainClass
{
    public static void Main ()
   {
        SampleDelagate del1 = new SampleDelagate (Method1);
        SampleDelagate del2 = new SampleDelagate (Method2);
        SampleDelagate del3 = new SampleDelagate (Method3);
        SampleDelagate del4 = del1 + del2 + del3;

        int ValueReturned = del4 ();

        //Del4 invokes Del1, Del2, Del3 in the same order. Here the return type is int. So the return of last delegate del3 is returned. Del3 points to Method3. So returned value is 3.

        Console.WriteLine (ValueReturned);

        //Output: 3
    }

    public static int Method1 ()
    {
        return 1;
    }

    public static int Method2 ()
    {
        return 2;
    }

    public static int Method3 ()
    {
        return 3;
    }
}

Method 2-

Same process as Type 1

So when there is a return type of a MultiCast Delegate the return value is the return value of last delegate.

Type 3:

int, int, ref int arguments and void return type delegate -

using System;

delegate void SampleDelegate (ref int SampleReferenceParameter);

class MainClass
{
    public static void Main ()
    {
        SampleDelegate del1, del2, del3, del4;
        del1 = new SampleDelegate (SampleMethodOne);
        del2 = new SampleDelegate (SampleMethodTwo);
        del3 = new SampleDelegate (SampleMethodTwo);
        del4 = del1 + del2 + del3 - del3;

        int SampleReferenceParameterValue = 0;
        del4 (ref SampleReferenceParameterValue);

        Console.WriteLine (SampleReferenceParameterValue); 
    }

    public static void SampleMethodOne (ref int SampleReferenceParameter)
    {
        SampleReferenceParameter = 1;
    }

    public static void SampleMethodTwo (ref int SampleReferenceParameter)
    {
        SampleReferenceParameter = 2;
    }

    public static void SampleMethodThree (ref int SampleReferenceParameter)
    {
        SampleReferenceParameter = 3;
    }
}

/*
Here del4 is first set as sum of del1, del2 and del3. Then del3 is subtracted from del4. So del4 now has del1, del2.

When del4 is invoked, first del1 and then del2 is invoked.

del1 sets reference parameter to 1. del2 sets reference parameter to 2.

But since del2 is called last final value of reference parameter is 2
*/
Ringler answered 27/12, 2017 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.