2009-04-22 24 views
33

Se si desidera creare delegati personalizzati, utilizzare la parola chiave delegato in lettere minuscole.Parola chiave delegato o delegato

Cosa si può fare con la classe di delegati effettiva? A cosa serve questo? Non capisco la differenza esatta.

risposta

34

Da http://msdn.microsoft.com/en-us/library/system.delegate.aspx:

La classe Delegate è la classe base per i tipi di delegati. Tuttavia, solo il sistema e i compilatori possono derivare esplicitamente dalla classe Delegate o dalla classe MulticastDelegate. Non è inoltre ammesso il di derivare un nuovo tipo da un tipo delegato. La classe Delegate non è considerata un tipo delegato ; è una classe utilizzata per i tipi di delegati derivati ​​da .

maggior parte dei linguaggi implementare una parola chiave delegate , e compilatori per quelle lingue sono in grado di derivare dalla classe MulticastDelegate; pertanto, gli utenti di devono utilizzare la parola chiave fornita dalla lingua.

+1

Nice fetch da MSDN;) – Xian

+0

http://msdn.microsoft.com/en-us/library/system.delegate.aspx – Xian

2

Il vantaggio della classe Delegate è che è la classe base per tutti i tipi di delegati in .Net. Avere un metodo che prende un'istanza di questa classe consente di operare genericamente su tutti i tipi di delegati. Questo è il motivo per cui operazioni come ISynchronizedInvoke.Invoke usano questo come parametro.

+4

Si noti tuttavia che invocare un delegato in questo modo è ritardato e (di conseguenza) più lento. –

34

La parola chiave delegata serve al compilatore per fare un po 'di magia per te. Quando dichiari un nuovo delegato con una firma personalizzata,

  • il compilatore crea un nuovo tipo per te derivato da MulticastDelegate (che a sua volta deriva da Delegato).
  • il compilatore aggiunge un metodo Invoke con la vostra firma personalizzata
  • allo stesso modo il compilatore aggiunge BeginInvoke e metodi EndInvoke per questo nuovo tipo di

Così ora quando si chiama delObject(args) - il compilatore traduce che per delObject.Invoke(args)

La classe di base Delegate fornisce alcune funzionalità come

  1. CreateDelegate (per ottenere un dele gate wrapping a static/instance method)
  2. DynamicInvoke (per richiamare un delegato con un elenco di argomenti - late binding)
  3. Combina e Rimuovi (per il delegato concatenamento .. catena più delegati insieme, ad es. più delegati di gestori di eventi per un evento)

Il compilatore C# vieta di derivare dal Delegato in modo esplicito nel codice .. è necessario utilizzare la parola chiave delegato.

+1

+1: in particolare per dire che "il compilatore crea un nuovo tipo per te derivato da MulticastDelegate" . Quindi, per impostazione predefinita, i delegati che creiamo sono tutti delegati Multicast – A9S6

+0

Chiaramente. Mi piace la tua risposta. –

+0

'il compilatore crea un nuovo tipo per te derivato da MulticastDelegate' Non sono sicuro di questo. Secondo http://msdn.microsoft.com/en-us/library/system.delegate.aspx 'Tuttavia, solo il sistema ei compilatori possono derivare esplicitamente dalla classe Delegate o dalla classe MulticastDelegate. Si noti la parola chiave" ** o ** " –

1

Da una prospettiva di implementazione, la classe Delegate definisce i campi utilizzati per rappresentare il puntatore di funzione di un delegato e la classe MultiCastDelegate fornisce la funzionalità di base utilizzata dagli eventi. Inoltre, come indicato da altre persone, Delegato fornisce il metodo "DynamicInvoke" che consente di richiamare qualsiasi delegato.

3

Un'altra cosa semplice si può fare con delegate parola chiave è creare delegati in linea, senza dover dichiarare loro, per esempio:

// constructor 
public Form1() 
{ 
    this.Load += delegate(object sender, EventArgs e) 
    { 
     // Form1_Load code goes right here 
    } 
} 
+3

La sintassi lambda C# 3.0 è molto meno dettagliata. –

2

Una delle cose che la classe Delegate può essere utilizzato per è un maggiore controllo quando si richiama gestori di eventi. Ad esempio, con l'elaborazione di eventi normale, un'eccezione in qualsiasi gestore di eventi impedirà il richiamo di eventuali gestori di eventi successivi. È possibile modificare tale comportamento utilizzando la classe Delegate per richiamare manualmente ciascun gestore di eventi.

using System; 

namespace DelegateClass 
{ 
    class EventSource 
    { 
     public event EventHandler TheEvent; 

     internal void RaiseEvent1() 
     { 
      EventHandler handler = TheEvent; 
      if (handler != null) 
       handler(this, EventArgs.Empty); 
     } 

     internal void RaiseEvent2() 
     { 
      EventHandler handler = TheEvent; 
      if (handler == null) 
       return; 

      Delegate[] handlers = handler.GetInvocationList(); 
      foreach (Delegate d in handlers) 
      { 
       object[] args = new object[] { this, EventArgs.Empty }; 
       try 
       { 
        d.DynamicInvoke(args); 
       } 
       catch (Exception ex) 
       { 
        while (ex.InnerException != null) 
         ex = ex.InnerException; 

        Console.WriteLine(ex.Message); 
       } 
      } 
     } 
    } 

    class Program 
    { 
     static void Handler1(object sender, EventArgs e) 
     { 
      Console.WriteLine("Handler1"); 
     } 

     static void Handler2(object sender, EventArgs e) 
     { 
      Console.WriteLine("Handler2"); 
      throw new InvalidOperationException(); 
     } 

     static void Handler3(object sender, EventArgs e) 
     { 
      Console.WriteLine("Handler3"); 
     } 

     static void Main(string[] args) 
     { 
      EventSource source = new EventSource(); 
      source.TheEvent += Handler1; 
      source.TheEvent += Handler2; 
      source.TheEvent += Handler3; 

      try 
      { 
       source.RaiseEvent1(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex.Message); 
      } 

      Console.WriteLine("-------------------"); 

      source.RaiseEvent2(); 
     } 
    } 
}