2010-01-29 14 views
8

Por ejemplo, tengo un método de evento de base editorial:.NET: ¿Está creando nuevos EventArgs cada vez que el evento desactive una buena práctica?

protected virtual OnSomeEvent(EventArgs e) 
    { 
     var handler = SomeEvent; 
     if (handler != null) 
     { 
      handler(this, e); 
      // handler(this, new EventArgs());// EDIT: Yes it should be 
              // handler(this, e), 
              // ignore this one :D 
     } 
    } 

Para una clase derivada que anula OnSomeEvent y provoca un evento adicional cuando se dispara:

protected override OnSomeEvent(EventArgs e) 
    { 
     base.OnSomeEvent(e); 

     if (ExtendedEvent != null) 
     { 
      OnExtendedEvent(e); 
     } 
    } 

    protected void OnExtendedEvent(EventArgs e) 
    { 
     // some stuff done 
     // new information the ExtendedEventArgs object needs 
     // is not available until this point 

     ExtendedEvent(this, new ExtendedEventArgs(someStuff, someOtherStuff)); 
    } 

Y si la derivación sigue así , creará un nuevo EventArgs derivado para cada generación de clase derivada que lo requiera. Sin embargo, parece que varias derivaciones de EventArgs en .NET Framework no están diseñadas para ser mutables (no setters), esto desalienta a un objeto de mantener una sola instancia de EventArgs y modificarla a medida que avanza.

Así que cada vez que un evento como este se activa, volverá a asignar memoria para todos los objetos EventArgs implicados. En una aplicación gráfica intensa donde un evento puede activarse docenas de veces por segundo (como el evento OnPaint en un control), ¿es realmente una buena práctica?

¿Debo hacer algunos cambios en OnExtendedEvent() y hacer ExtendedEventArgs mutable entonces el siguiente es posible?

protected ExtendedEventArgs extendedArgs = ExtendedEventArgs.Empty; 
    protected void OnExtendedEvent(EventArgs e) 
    { 
     // some stuff done 
     // new information the ExtendedEventArgs object needs 
     // is not available until this point 

     extendedArgs.someProperty1 = someStuff; 
     extendedArgs.someProperty2 = someOtherStuff; 

     ExtendedEvent(this, extendedArgs); 
    } 

EDITAR: corrigió el código de ejemplo, debería ser más claro ahora.

+1

La derivación no es un problema, la clase derivada solo puede llamar a base.OnExtendedEvent con EventArgs.Empty. En general, no tengas miedo de crear basura de corta vida. –

+0

Creo que te refieres a inmutable en lugar de mutable. Inmutable significa que no puedes cambiarlo. – aaronb

Respuesta

3

Crearía un nuevo objeto inmutable cada vez que se dispara, ya que hay valores en los argumentos del evento.

La razón principal es ¿qué pasaría si un nuevo evento se activa nuevamente mientras se está manejando un evento existente?

Esto posiblemente sucederá en aplicaciones multi-hilo pero incluso puede ocurrir en un solo hilo como se muestra en el siguiente ejemplo:

primer evento se activa con los siguientes valores:

extendedArgs.someProperty1 = "Fire 1"; 
extendedArgs.someProperty2 = "Fire 1 Other Stuff"; 

entonces de alguna manera el primer controlador de eventos hace algo hace que el evento que se disparó de nuevo con los siguientes argumentos:

extendedArgs.someProperty1 = "Fire 2"; 
extendedArgs.someProperty2 = "Fire 2 Other Stuff"; 

Todos los controladores de eventos ar e para el segundo evento se procesan, y ahora estamos de vuelta para procesar el resto de los manejadores de eventos para el primer evento.

Ahora, dado que se utiliza el mismo objeto, todos los controladores de eventos para el primer evento ahora tendrán "Fire 2" como su someProperty1, ya que el segundo evento sobrescribió los valores.

Como se menciona @nobugz, no tengas miedo de crear basura de corta vida.

1

Estoy un poco confundido por su código OnExtendedEvent - ¿Quiere volver a enviar el evento como SomeEvent?

Cuando un cliente agrega un controlador de eventos, se espera que sean capaces de eliminar el controlador de eventos durante la manipulación del evento, así:

someObject.SomeEvent += OnSomeEvent; 
// ... 
private void OnSomeEvent(object sender, EventArgs e) 
{ 
    someObject.SomeEvent -= OnSomeEvent; 
} 

Si usted no sigue la práctica de despacho estándar, este código lanza una excepción para sorpresa de la persona que usa tu código.

+0

Hola, lo siento, el código ES confuso. Corregido ahora: D – Dan7

5

En primer lugar, ¿por qué llevar un argumento de EventArgs a su método de disparo si lo ignora de todos modos? Ese es el desperdicio real, pero el consumo de recursos es menos problemático que la mentira que su método les está diciendo a sus interlocutores. Sólo tiene que pasar el argumento a través de, su método de cocción probablemente no tendrá información pertinente sea accesible para crear los EventArgs objeto de todos modos:

protected virtual OnSomeEvent(EventArgs e) 
{ 
    var handler = SomeEvent; 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

Así que, ahora que tenemos que recta, si sus EventArgs objeto no tiene información significativa para contar sus suscriptores, solo use EventArgs.Empty, eso es para lo que está ahí. Puede seguir el mismo patrón para sus clases personalizadas de EventArgs, pero sinceramente, no se está preocupando por nada. Crear objetos EventArgs nunca será un cuello de botella en su aplicación, y si lo es, tendrá problemas de diseño.

Cuestiones relacionadas