2010-12-21 61 views
19

Tengo un evento en un bucle. Estoy tratando de evitar que se agregue el mismo método a un evento más de una vez. Implementé los accesos add y remove.-evento- solo puede aparecer en el lado izquierdo de + = o - =

Sin embargo, me sale un error que indica que:

ItemsProcessed can only appear on the left hand side of += or -=

Cuando intento llamar, incluso dentro de la misma clase.

ItemsProcessed(this, new EventArgs()); // Produces error 

public event EventHandler ItemsProcessed 
{ 
    add 
    { 
     ItemsProcessed -= value; 
     ItemsProcessed += value; 
    } 
    remove 
    { 
     ItemsProcessed -= value; 
    } 
} 
+3

Además, parece que ha creado un bucle infinito al acceder a 'ItemsProcessed' dentro de las funciones' ItemsProcessed'. – Gabe

+0

Como referencia, el truco de invocación 'EventName (args)' solo se aplica a los * eventos tipo campo *, donde algunas operaciones se resuelven implícitamente al * campo * (no el evento) dentro de la clase. Tengo que decir "algo", porque la lista exacta cambió entre C# 3 y C# 4. –

Respuesta

19

Con un evento explícito, es necesario proporcionar su propio almacén de respaldo - ya sea un campo delegado o algo así EventHandlerList. El código actual es recursivo. Proveedores:

private EventHandler itemsProcessed; 
public event EventHandler ItemsProcessed 
{ 
    add 
    { 
     itemsProcessed-= value; 
     itemsProcessed+= value; 
    } 

    remove 
    { 
     itemsProcessed-= value; 
    } 
} 

Entonces (y teniendo en cuenta que estoy siendo un poco cauteloso sobre el "punto de cumplir null" borde de los casos re threading):

var snapshot = itemsProcessed; 
if(snapshot != null) snapshot(this, EventArgs.Empty); 

Con las versiones más recientes de C#, esto se puede simplificar:

itemsProcessed?.Invoke(this, EventArgs.Empty); 
+1

Una desventaja: solo accesible dentro de una clase –

+2

¿Por qué querrías acceder a un evento de respaldo privado fuera de una clase? –

+0

Subclases, duh. Hacer cosas protegidas – Nyerguds

1

¿Qué error? Supongo que es un error de desbordamiento de la pila, porque está llamando agregar y eliminar en yourserlf (mismo evento). Tampoco puedes subir el evento ACCESSOR.

Una forma válida de hacerlo es crear un evento privado de respaldo, que se agregará y eliminará del acceso público, y debe plantear este evento privado.

Dang, minuto tarde.

+1

No, él no sabe sobre el desbordamiento de pila porque su código ni siquiera se compila. – Gabe

+0

Sí, dejé de pensar en ello cuando se publicó la respuesta de Marc. Tienes razón. – Euphoric

7

Parece que si implementa el EventHandler explícitamente, no puede consultar la 'Propiedad' al disparar el evento. Debe consultar la tienda de respaldo.

4

No puedo decir por tu publicación si estás tratando de plantear el evento de una clase derivada o no, pero una cosa que encontré es que no puedes definir un evento en una clase base y luego subir es (directamente) en una clase derivada, por alguna razón que todavía no es muy clara para mí.

funciones Así defino protegidas en las clases base para elevar eventos (que se definen en las clases base), como esto:

// The signature for a handler of the ProgressStarted event. 
// title: The title/label for a progress dialog/bar. 
// total: The max progress value. 
public delegate void ProgressStartedType(string title, int total); 

// Raised when progress on a potentially long running process is started. 
public event ProgressStartedType ProgressStarted; 

// Used from derived classes to raise ProgressStarted. 
protected void RaiseProgressStarted(string title, int total) { 
    if (ProgressStarted != null) ProgressStarted(title, total); 
} 

A continuación, en la clase derivada, me llaman RaiseProgressStarted (título, total) en lugar de llamar a ProgressStarted (título, total).

Parece una especie de largo camino alrededor. Tal vez alguien más sepa de una mejor manera de resolver este problema.

+0

Me acabo de dar cuenta de que esta es una publicación de 5 años. Me encontré con el problema y descubrí lo que estaba pasando para mí, así que publiqué esta respuesta. Quizás sea útil para alguien. – Shavais

+0

Heh, acabo de tener este problema otra vez, no podía recordar qué lo había causado y cómo lo había solucionado, y encontré mi propia respuesta de hace 11 meses. Eso es bastante gracioso. – Shavais

Cuestiones relacionadas