2010-02-03 10 views
56

Ho esaminato molti articoli ma non sono ancora chiaro sulla differenza tra i delegati normali che di solito creiamo e i delegati multicast.Delegato semplice (delegato) e delegati multicast

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

Il suddetto delegato MyMethodHandler chiamerà questi due metodi. Ora da dove arrivano i delegati multicast. Ho letto che possono chiamare più metodi, ma temo che le mie conoscenze di base sui delegati non siano corrette.

risposta

67

This article spiega abbastanza bene:

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

Sono delegati multicast niente di più delegati normali che hanno più riferimenti di metodo nella loro lista di invocazione? – A9S6

+3

Esattamente. Un delegato multicast invocherà più metodi. –

+1

OK. Giusto per rendere più chiaro: dichiaro un delegato normale e aggiungere un metodo di riferimento, ora questo sarà chiamato delegato di Singlecast. Ora aggiungo un altro metodo allo stesso delegato, questo verrà ora indicato come un delegato multicast? – A9S6

42

Il C# disciplinare prevede che tutti i tipi delegato deve essere convertibile in System.Delegate. In effetti il ​​modo in cui l'implementazione implementa questo è che tutti i tipi di delegati sono derivati ​​da System.MulticastDelegate, che a sua volta deriva da System.Delegate.

È chiaro? Non sono sicuro che abbia risposto alla tua domanda.

+23

Sì, Eric. Normalmente quando chiedo ai delegati persone (o persone che mi chiedono), di solito diciamo che ci sono due tipi di delegati: Singlecast e Multicast. Ora so che esiste una sola cosa come un "delegato" che può essere singlecast o multicast a seconda del numero di riferimenti al metodo che contiene. – A9S6

11

"Tutte le istanze delegate hanno capacità multicast". - http://msdn.microsoft.com/en-us/library/orm-9780596527570-03-04.aspx

"In C#, tutti i tipi di delegare il supporto multicast" - http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx

+0

In che modo * qualsiasi istanza * delegata ha la capacità di richiamare un numero qualsiasi di azioni diverse dal numero che è stato creato per eseguire? Se un delegato è stato creato per invocare tre cose, penserei che l'istanza delegata farà sempre tre cose. Allo stesso modo, se è stato creato per fare una cosa. Se un delegato è stato creato per fare esattamente una cosa, come può mai quell'istanza fare di più? – supercat

+0

@supercat, non è così. –

+0

Che cosa significa "tutte le istanze delegate * hanno capacità multicast"? Certamente, tutti i tipi * delegati * hanno tale capacità e il codice che accetta un delegato per qualsiasi cosa diversa da una sottoscrizione di eventi deve essere preparato affinché sia ​​un delegato multicast (se un evento utilizza delegati multicast internamente, passando un delegato multicast a ' Il metodo Add' e il successivo passaggio a 'Remove' potrebbero non annullare la sottoscrizione dell'evento, ovvero che il malfunzionamento dei gestori di eventi predefiniti in questo modo implica che gli eventi non tollerino gli eventi multicast. – supercat

3

Per chiarire un po ': Tutti i delegati sono istanze della classe MulticastDelegate, indipendentemente dal fatto che hanno uno o più metodi di destinazione. In linea di principio non vi sono differenze tra un delegato con un singolo o più target, sebbene il tempo di esecuzione sia ottimizzato un po 'verso il caso comune con un singolo target. (Un delegato con 0 Obiettivi non è possibile, però, si tratta di uno o più.)

Quando si è un'istanza di un delegato come new MyMethodHandler(Method1), si crea un delegato con un singolo bersaglio (il metodo Method1).

I delegati con più destinazioni vengono creati combinando due delegati esistenti. Il delegato risultante avrà la somma degli obiettivi. I delegati possono essere combinati esplicitamente con Delegate.Combine(), ma anche implicitamente utilizzando l'operatore += su un delegato esistente, come nell'esempio.

Invocare un delegato a turno chiama ogni destinazione nel delegato. Quindi nell'esempio handler(someObject); chiamerà due metodi (Method1 e Method2), poiché è stato creato un delegato con questi due obiettivi.

-2

Un delegato multicast è un delegato che ha riferimenti a più di una funzione. Quando si richiama un delegato multicast, vengono richiamate tutte le funzioni a cui punta il delegato.

Tipo 1:

0 argomenti e vuoto tipo restituito delegato -

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

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

Tipo 2:

0 argomenti e tipo int di ritorno delegato

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

Metodo 2-

stesso processo di tipo 1

Quindi, quando c'è un tipo di ritorno di un Delegato MultiCast, il valore di ritorno è il valore di ritorno dell'ultimo delegato.

Tipo 3:

int, int, int argomenti ref e vuoto tipo di ritorno delegato -

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