2011-01-31 15 views
7

De MSDN:C# Delegados y método firmas

Cualquier método que coincide con la firma del delegado, que consiste en el tipo retorno y parámetros, pueden ser asignado al delegado.

Entonces, ¿cómo es esto posible:

public delegate void AlarmEventHandler(object sender, EventArgs e); 
public event AlarmEventHandler Alarm; 

protected virtual void OnAlarm(EventArgs e) 
     { 
      AlarmEventHandler handler = Alarm; 
      if (handler != null) 
      { 
       // Invokes the delegates. 
       handler(this, e); 
      } 
     } 

delegado AlarmEventHander y eventos AlarmEventHandler tienen diferentes firmas aún handler se pueden asignar a Alarm.

Tal vez estoy malinterpretando a los delegados de alguna manera, y estaría muy agradecido si alguien pudiera explicarme dónde me estoy equivocando.

+0

Creo que ha confundido algunos de los nombres de sus símbolos. En el código anterior, el delegado se llama 'AlarmEventHandler' y el evento, que es del mismo tipo, se llama' Alarm'. Como son del mismo tipo, no hay ningún problema con la tarea. Creo que lo que te confunde es el método 'OnAlarm' que parece responder a un evento diferente con un tipo de delegado diferente. –

+0

Ver: eventos similares a campos. http://msdn.microsoft.com/en-us/library/aa664455(v=vs.71).aspx – Ani

+0

No veo el problema aquí. Los tipos coinciden exactamente (ambos son 'AlarmEventHandler'), por lo que uno esperaría poder asignar uno al otro. – finnw

Respuesta

7

Un delegado es como una clase. Un evento es como una propiedad. Cuando declara un event en una clase, declara el tipo del evento que es. En este caso, AlarmEventHandler, que es clase interna de la clase de nivel superior de la que es parte.

En el método OnAlarm, obtiene la instancia de la clase AlarmEventHandler que se ha asignado al evento y la invoca.

para aclarar las cosas, el código anterior es similar a esto, el uso de clases normales & referencias:

public class InnerClass { 
    public void MyMethod() { /* ... */ } 
} 

public InnerClass MyProperty { get; set; } 

protected virtual void CallMyMethod() { 
    InnerClass cls = MyProperty; 
    if (cls != null) 
     cls.MyMethod(); 
} 
+0

me gusta la forma en que lo explicaste. me hizo imaginar cómo funciona mejor – Notter

2

En realidad las firmas son los mismos. En eventos .NET se implementan con delegados.

public event AlarmEventHandler Alarm; 

Así código anterior es en realidad compilado por el compilador como:

private AlarmEventHandler handler; 

public event AlarmEventHandler Alarm 
{ 
    add { handler += value; } 
    remove { handler -= value; } 
} 

Así evento realmente utiliza el mismo AlarmEventHandler delegado.

0
  1. Estás mezclando delegados y eventos. Si bien los eventos dependen de los delegados, son conceptos de diferencia completamente. Entonces debería tomarse por separado.
  2. Delegado es como la definición de tipo. El lugar donde usa este delegado es como variable o propiedad.
  3. El evento hace que este delegado se comporte de manera diferente desde el exterior. La firma sigue siendo la misma.
-3

Una función que toma una clase base como parámetro (sin referencia) se puede convertir a un delegado que toma una clase derivada como parámetro. Esto se debe a que la función que toma como base puede ser sustituida de forma segura siempre que se utilice una función que tome una clase derivada.

void TakesObject(object o) 
{ 
... 
} 

Action<string> myAction=TakesObject; 

Puede llamar a myAction solo pasando una cadena. Y dado que cada cadena es un objeto, se cumple el contrato de TakesObject.

En su caso es porque cada AlarmEventArgs es un EventArgs también.Por lo tanto, los requisitos de contrato de su controlador de eventos son menos estrictos que las garantías contractuales del tipo de delegado utilizado por el evento.

Esto se llama contra-varianza y contra-varianza. Tiene co-varianza en los tipos de retorno y contra varianza en los parámetros.

Comprobar este artículo en MSDN:
Using Variance in Delegates (C# and Visual Basic)

0

Un evento es sólo un delegado. El delegado itselft solo se puede acceder desde el interior de la clase. Desde el exterior, solamente añadir y eliminar funcionalidad para el evento es posible que sólo se puede hacer esto:

myAlarm.Alarm+=new AlarmEventHandler(callPolice); 
// or 
myAlarm.Alarm-=new AlarmEventHandler(callPolice); 

Pero desde el interior de la clase, la alarma es sólo un delegado de tipo AlarmEventHandler por lo usted puede hacer lo que muestra su código:

 AlarmEventHandler handler = Alarm; 
     if (handler != null) 
     { 
      // Invokes the delegates. 
      handler(this, e); 
     }