简单委托(委托)与多播委托

问题描述 投票:59回答:6

我已经阅读了很多文章,但我仍然不清楚我们通常创建的普通代表和多播代理之间的区别。

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

上面的委托MyMethodHandler将调用这两个方法。现在多播代表的位置在哪里。我已经读过它们可以调用多种方法,但我担心我对代理的基本理解是不正确的。

c# .net delegates multicastdelegate
6个回答
72
投票

This article解释得很好:

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!
*/

47
投票

C#规范规定所有委托类型必须可转换为System.Delegate。事实上,实现实现这一点的方式是所有委托类型都是从System.MulticastDelegate派生的,System.Delegate又派生自http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx

明白了吗?我不确定是否回答了你的问题。


11
投票

“所有委托实例都具有多播功能。” - http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx

“在C#中,所有委托类型都支持多播” - MulticastDelegate


5
投票

澄清一点:所有代表都是类new MyMethodHandler(Method1)的实例,无论它们是否有一个或多个目标方法。原则上,具有单个或多个目标的委托之间没有区别,尽管运行时针对具有单个目标的常见情况稍微优化。 (虽然不可能有0个目标的代表,但它是一个或多个。)

当您实例化像Method1这样的委托时,您可以创建一个具有单个目标的委托(Delegate.Combine()方法)。

通过组合两个现有委托来创建具有多个目标的代理。结果代表将拥有目标总和。代理可以与+=明确组合,但也可以在现有委托中使用handler(someObject);运算符隐式组合,如示例所示。

调用委托依次调用委托中的每个目标。所以在你的例子中,Method1会调用两个方法(Method2http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx),因为你已经用这两个目标创建了一个委托。


4
投票

很抱歉添加到其他人的答案,但我认为代表是按照添加的顺序调用的。

“多播代理”部分

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"); } }


-3
投票

多播委托是一个委托,它引用了多个函数。当您调用多播委托时,将调用委托指向的所有函数。

类型1:

0参数和void返回类型委托 -

方法1 -

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");
    }
}

方法2 -

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;
    }
}

类型2:

0参数和int返回类型委托

方法1-

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
*/

方法2-

与类型1相同的过程

因此,当存在MultiCast Delegate的返回类型时,返回值是最后一个委托的返回值。

类型3:

int,int,ref int参数和void返回类型委托 -

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.