2011-08-20 8 views
6

Si escribo algo así como el código de abajo,¿Por qué los eventos con acceso directo personalizado no pueden activarse directamente como lo hacen los predeterminados?

class MainClass 
{ 
    static EventHandler _myEvent= delegate{}; 
    static event EventHandler MyEvent 
    { 
     add{_myEvent += value;} 
     remove{_myEvent -= value;} 
    } 

    public static void Main (string[] args) 
    { 
     MyEvent(null,EventArgs.Empty); 
    } 
} 

el compilador se quejará: CS0079 de error: El evento MainClass.MyEvent' can only appear on the left hand side of + = 'o' - =' operador.

¿Por qué existe algo tan extraño como esto? Si no puedo lanzar un evento directamente, ¿por qué usaría tal cosa en primer lugar? ¿Es eso un error (estoy usando mono) o deliberadamente delicado diseño? ¿Alguien podría por favor enseñarme la razón detrás de esto? Gracias por adelantado.

Respuesta

2

Solo puede acceder a un evento en la clase declarante. Detrás de escena, .NET crea variables de instancia privadas para contener el delegado.

El compilador en realidad está creando un evento público y un campo privado. Puede acceder al campo directamente desde la misma clase o clases anidadas. Desde clases externas, solo se le podría suscribir/cancelar suscripción.

Gran información de Jon Skeet está disponible here sobre por qué esto es así y cómo funciona.

+0

Ese no es el problema aquí. El intento de acceder al evento _es_ desde dentro de la clase declarante ... –

+0

@Nick: No, esto es absolutamente lo que está sucediendo: para un evento tipo campo, una llamada que parece estar invocando el evento está realmente invocando a través del campo . Luego, toma ese conocimiento y lo aplica al evento personalizado, invocando * that * a través del campo de respaldo también. –

+0

@Jon: estoy de acuerdo en que puede retroceder en la forma en que se implementan los eventos de campo para comprender el error CS0079. Si la respuesta se hubiera concentrado en eso, hubiera sido +1 y hecho por mí. Sin embargo, la respuesta se centra en la accesibilidad privada del campo, y eso está al lado del punto. –

2

Debe invocar su delegado de respaldo declarado manualmente para plantear el evento: reemplace MyEvent(null, EventArgs.Empty) con _myEvent(null, EventArgs.Empty). Si lo piensas bien, el agregar/quitar personalizado podría almacenar a los delegados en cualquier parte, por lo que no puedes recuperarlos e invocarlos de la forma que lo has escrito ...

+0

: Pero, ¿y si quiero? derivar la clase y no quiero exponer el campo delegado subyacente a la subclase? Eso será un desastre, ¿no? Acabo de observar que las subclases no pueden disparar los eventos de su clase base. ¿No es este diseño un poco débil? Los eventos se emplean para evitar que los extraños lo arruinen. Pero, ¿por qué los de adentro también están restringidos? – Need4Steed

+0

El patrón recomendado es proporcionar un método virtual protegido que genere el evento: http://msdn.microsoft.com/en-us/library/ms229011.aspx. –

+1

Gracias por su enlace. Sin embargo, sigo pensando que el diseño de no permitir fuego es bastante cojo. Los eventos pueden ser virtuales y ser reemplazados por subclases, pero para dispararlos, tenemos que recurrir a algunos métodos virtuales de ayuda, ¿cómo es que no es cojo? – Need4Steed

Cuestiones relacionadas