2009-04-22 31 views
33

Si desea crear delegados personalizados, utilice la palabra clave de delegado en minúsculas.delegado vs. delegar palabra clave

¿Qué se puede hacer con la clase real de delegados? ¿Para qué es bueno esto? No entiendo la diferencia exacta.

Respuesta

34

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

La clase Delegate es la clase base para este tipo de delegado. Sin embargo, solo el sistema y los compiladores pueden derivar explícitamente de la clase Delegate o de la clase MulticastDelegate. No es posible derivar un nuevo tipo de un tipo de delegado. La clase Delegate no se considera un tipo de delegado ; es una clase utilizada para derivar tipos de delegados.

mayoría de los lenguajes implementar una palabra clave delegate y compiladores para aquellos lenguas son capaces de derivar de la clase MulticastDelegate; por lo tanto, los usuarios de deben usar la palabra clave delegate proporcionada por el idioma.

+1

Niza buscarlo a MSDN;) – Xian

+0

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

2

La ventaja de la clase Delegate es que es la clase base para todos los tipos de delegados en .Net. Tener un método que toma una instancia de esta clase le permite operar de manera genérica sobre todo tipo de delegados. Este es el motivo por el que operaciones como ISynchronizedInvoke.Invoke lo utilizan como parámetro.

+4

Sin embargo, debe tenerse en cuenta que la invocación de un delegado de esta manera está atrasada y (en consecuencia) más lenta. –

34

La palabra clave delegar es para que el compilador haga algo mágico por usted. Cuando declara un nuevo delegado con una firma personalizada,

  • el compilador crea un nuevo Tipo para usted derivado de MulticastDelegate (que a su vez deriva de Delegate).
  • el compilador agrega un método de invocación con su firma personalizada
  • Del mismo modo el compilador añade BeginInvoke y métodos EndInvoke de este nuevo tipo

Así que ahora cuando se llama delObject(args) - el compilador traduce eso a delObject.Invoke(args)

La clase base del delegado proporciona algunas funciones, como

  1. CreateDelegate (para obtener un delegado) puerta envolver un método estático/ejemplo)
  2. DynamicInvoke (para invocar un delegado con una lista de argumentos - tarde unido)
  3. combinar y eliminar (para delegado encadenamiento .. cadena múltiples delegados juntos, por ejemplo, múltiples delegados controladores de eventos para un evento)

El compilador de C# le prohíbe derivarse de Delegate explícitamente en su código ... tiene que usar la palabra clave delegar.

+1

1: Especialmente mencionar que "el compilador crea un nuevo tipo para usted derivados de MulticastDelegate" . De manera predeterminada, los delegados que creamos son todos delegados de Multidifusión – A9S6

+0

Claramente. Me gusta tu respuesta. –

+0

'el compilador crea un nuevo tipo para usted derivado de MulticastDelegate' No estoy seguro de esto. De acuerdo con http://msdn.microsoft.com/en-us/library/system.delegate.aspx 'Sin embargo, sólo el sistema y los compiladores pueden derivar explícitamente de la clase Delegate o desde el class.' MulticastDelegate Tenga en cuenta la palabra clave" ** o ** " –

1

Desde una perspectiva de aplicación, la clase Delegate define los campos que se utilizan para representar puntero de función de un delegado y la clase MulticastDelegate proporciona la funcionalidad de línea de base utilizada por los acontecimientos. Además, como mencionan otras personas, Delegate proporciona el método "DynamicInvoke" que le permite invocar a cualquier delegado.

3

Otra cosa ordenada que puede hacer con delegate palabra clave es crear delegados en línea, sin tener que declararlos, por ejemplo:

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

La sintaxis lambda de C# 3.0 es mucho menos detallada. –

2

Una de las cosas de la clase Delegate se puede utilizar para un mayor control cuando se invoca manejadores de eventos. Por ejemplo, con el procesamiento de eventos normal, una excepción en cualquier controlador de eventos evitará que se llame a los controladores de eventos posteriores. Puede modificar ese comportamiento utilizando la clase Delegate para invocar manualmente cada controlador de eventos.

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