2010-01-29 1 views
8

Per esempio, Ho un metodo di base dell'editoria evento:. NET: la creazione di nuovi eventi ogni volta che l'evento genera una buona pratica?

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 
     } 
    } 

Per una classe derivata che prevale su OnSomeEvent e genera un evento aggiuntivo quando si spara:

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)); 
    } 

E se derivazione continua così , creerà un nuovo EventArgs derivato per ogni generazione di classe derivata che lo richiede. Tuttavia sembra che le varie derivazioni di EventArgs nel framework .NET non siano progettate per essere mutabili (nessun setter), questo scoraggia un oggetto dal mantenere una singola istanza di EventArgs e modificarlo man mano che procede.

Quindi ogni volta che si attiva un evento come questo, viene riallocata la memoria per tutti gli oggetti coinvolti EventArgs. In un'applicazione grafica intensa in cui un evento può essere attivato decine di volte al secondo (come ad esempio l'evento OnPaint su un controllo), è davvero una buona pratica?

Devo apportare alcune modifiche a OnExtendedEvent() e rendere modificabile ExtendedEventArgs in modo che quanto segue sia possibile?

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); 
    } 

MODIFICA: corretto il codice di esempio, ora dovrebbe essere più chiaro.

+1

Derivazione non è un problema, la classe derivata può solo chiamare base.OnExtendedEvent con EventArgs.Empty. In generale, non aver paura di creare spazzatura di breve durata. –

+0

Penso che tu intenda immutabile invece che mutabile. Immutabile significa che non puoi cambiarlo. – aaronb

risposta

3

Vorrei creare un nuovo oggetto immutabile ogni volta che viene generato, in quanto vi sono valori negli argomenti dell'evento.

Il motivo principale è che cosa accadrebbe se un nuovo evento viene generato nuovamente mentre viene gestito un evento esistente?

Ciò accadere in applicazioni multi-thread, ma può anche avvenire su un singolo filo, come illustrato dal seguente esempio:

primo evento viene generato con i seguenti valori:

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

Poi qualche modo il primo gestore di eventi fa qualcosa fa sì che l'evento da sparò di nuovo con i seguenti argomenti:

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

Tutti i gestori di eventi ar e per il secondo evento vengono elaborati e ora torniamo all'elaborazione del resto dei gestori di eventi per il primo evento.

Ora poiché viene utilizzato lo stesso oggetto, tutti i gestori di eventi per il primo evento avranno "Fuoco 2" come loroProprietà1, in quanto il secondo evento ha sovrascritto i valori.

Come menzionato @nobugz, non abbiate paura di creare una spazzatura di breve durata.

1

Sono un po 'confuso dal codice OnExtendedEvent - si intende ridispatchare l'evento come SomeEvent?

Quando un client aggiunge un gestore di eventi, che si aspettano sono in grado di rimuovere il gestore di eventi durante la gestione dell'evento, in questo modo:

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

Se non si segue la prassi di dispacciamento di serie, questo codice lanciare un'eccezione per la sorpresa della persona che usa il tuo codice.

+0

Ciao, scusa, il codice è confuso. Risolto ora: D – Dan7

5

Prima di tutto, perché prendere un argomento EventArgs per il metodo di sparo se lo si sta ignorando comunque? Questo è il vero spreco, ma il consumo di risorse è meno problematico della bugia che il tuo metodo sta dicendo ai suoi chiamanti. Basta passare l'argomento attraverso, il metodo di cottura probabilmente non avrà informazioni utili e accessibili per creare le EventArgs opporsi in ogni caso:

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

Così, ora che abbiamo che dritto, se i vostri EventArgs oggetto non ha informazioni significative da raccontare i tuoi iscritti, basta usare EventArgs.Empty, ecco a cosa serve. Puoi seguire lo stesso schema per le tue classi EventArgs personalizzate, ma onestamente, ti preoccupi di nulla. La creazione di oggetti EventArgs non costituirà mai un collo di bottiglia nell'applicazione e, in caso affermativo, si avranno problemi di progettazione.