2011-11-15 6 views
6

Me pregunto si hago algo como esto:C# eventos y métodos de la clase

class A 
{ 
    public MethodA() 
    { 
    } 
    public MethodB() 
    { 
     ExternalObject.Click += this.MethodA; 
    } 
    public MethodC() 
    { 
     ExternalObject.Click -= this.MethodA; 
    } 
} 

A a = new A(); 
a.MethodB(); 
a.MethodC(); 

¿Esto va a trabajar? Me refiero al "trabajo": ¿se anulará la suscripción al MethodA del evento ExternalObject.Click?

Y otras preguntas relacionadas:

Lo que sucede detrás de las escenas cuando se utiliza un método de instancia en lugar de ejemplo delegado? (como arriba)

¿Esto causa la creación implícita de un delegado?

¿Cómo realiza el operador -= la comparación entre delegados, por referencia o tal vez sucede algo más sofisticado?

Respuesta

8

Sí, funcionará como usted lo desee.

La comparación no es por referencia, es por valor, lo que significa que puede darse de baja de un delegado diferente, siempre que apunte al mismo método en el mismo objeto.

En otras palabras, esto va a funcionar muy bien:

var delegate1 = new ExternalObjectClickEventHandler(MethodA); 
var delegate2 = new ExternalObjectClickEventHandler(MethodA); 
ExternalObject.Click += delegate1; 
ExternalObject.Click -= delegate2; 

métodos anónimos son diferentes, sin embargo, no se puede hacer esto:

public MethodB() 
{ 
    ExternalObject.Click +=() => { return 10; }; 
} 

public MethodC() 
{ 
    ExternalObject.Click -=() => { return 10; }; 
} 

Mientras que los métodos contienen el mismo código, que se consideran diferente, y por lo tanto, esto no funcionará, es decir, MethodC no cancelará la suscripción al delegado que haya agregado en MethodB.

Para resolver este problema, usted tiene que almacenar el delegado entre invocaciones, como esto:

private ExternalObjectClickEventHandler _ClickEventHandler; 
public MethodB() 
{ 
    _ClickEventHandler =() => { return 10; }; 
    ExternalObject.Click += _ClickEventHandler; 
} 

public MethodC() 
{ 
    ExternalObject.Click -= _ClickEventHandler; 
} 

Pero el código que mostró, va a trabajar.

cuanto a su pregunta lo que sucede detrás de las escenas, es que las siguientes dos líneas de código son idénticos cuando se trata de código generado:

ExternalObject.Click += MethodA; 
ExternalObject.Click += new ExternalObjectClickEventHandler(MethodA); 

El segundo código es lo que se genera a partir de la primera (suponiendo el tipo del evento es como se muestra).

La primera sintaxis fue (en algún momento) agregada como "azúcar sintáctico" que el compilador traduce como si hubiera escrito la segunda sintaxis. Tenga en cuenta que esto solo ocurre si el compilado puede determinar el tipo correcto al 100%. He visto algunos casos (que no recuerdo ahora) en los que tenías que usar la sintaxis completa porque el compilador no podía entender lo que querías decir. En particular, las sobrecargas de métodos y los genéricos pueden confundirlo a este respecto.

+0

Gracias por una respuesta completa. – kubal5003

3

Sí, MethodA se cancelará la suscripción.

Sobre la segunda pregunta no estoy 100% seguro, pero creo que = this.MethodA se convierte en un delegado en segundo plano.

+0

+1. 'this.MethodA' se convertirá implícitamente en un delegado. – kol

Cuestiones relacionadas