2010-05-27 23 views
9

Ho esaminato la gestione della memoria molto di recente e ho analizzato il modo in cui gli eventi sono gestiti, ora vedo la sintassi aggiunta/rimuovi esplicita per la sottoscrizione dell'evento.Evento/aggiunta Evento esplicito, incompreso?

Penso che sia piuttosto semplice, aggiungi/rimuovi mi consente di eseguire altre logiche quando mi iscrivo e disiscrivo? Lo sto prendendo o c'è dell'altro?

Inoltre, mentre sono qui, qualsiasi consiglio/procedura consigliata per pulire le maniglie dell'evento.

risposta

3

Aggiungere/rimuovere la sintassi è comunemente utilizzato per "inoltrare" un'implementazione di un evento in un'altra classe.

La pulizia degli abbonamenti (non di "handle di evento") viene eseguita meglio implementando IDisposable.

AGGIORNAMENTO: C'è qualche variazione su quale oggetto dovrebbe implementare IDisposable. Il team Rx ha preso la decisione migliore dal punto di vista del design: gli abbonamenti stessi sono IDisposable. Gli eventi .NET regolari non hanno un oggetto che rappresenta la sottoscrizione, quindi la scelta è tra il publisher (la classe su cui è definito l'evento) e il sottoscrittore (di solito la classe che contiene la funzione membro che viene sottoscritta). Mentre il mio istinto di progettazione preferisce rendere l'utente IDisposable, la maggior parte del codice del mondo reale rende l'editore IDisposable: è un'implementazione più semplice e potrebbero esserci casi in cui non esiste un'istanza di sottoscrizione effettiva.

(Cioè, se il codice pulisce in realtà le sottoscrizioni di eventi a tutti. La maggior parte del codice non lo fa.)

+0

Ha, mi riferisco a loro come abbonamenti quando parlo con i miei colleghi eppure nel momento in cui invio una domanda, sto usando la terminologia sbagliata. Grazie per il chiarimento. – Hammerstein

6

Sì, l'add/rimuovere la sintassi consente di implementare la propria logica di sottoscrizione. Quando li lasci fuori (la notazione standard per un evento) il compilatore genera implementazioni standard. È come le proprietà automatiche.

Nel seguente esempio, non c'è alcuna differenza reale tra Evento1 ed Evento2.

public class Foo 
{ 
    private EventHandler handler; 
    public event EventHandler Event1 
    { 
    add { handler += value; } 
    remove { handler -= value; } 
    } 

    public event EventHandler Event2; 
} 

Ma questo è un argomento separato dai gestori di "pulizia". È la classe di iscrizione che dovrebbe annullare l'iscrizione. La classe editoriale non può aiutarci molto.
Immagina una classe che "pulisce" l'elenco di sottoscrizioni dei suoi eventi. Può farlo in modo sensato solo quando è Smaltito da solo, e quindi è improbabile che sia produttivo poiché una classe Disposed di solito diventa raccoglibile poco dopo essere stata Smaltita.

+1

Credo che un utente finale non possa fare: 'Foo foo = ...; foo.Event1 (sender, e); 'ma potrebbe fare' foo.Event2 (null, null); '. – user7116

+0

Grazie per l'esempio e il chiarimento. Pensavo di averlo, ma ci stavo pensando! Pubblicherò la mia domanda sulla gestione della memoria in una domanda a parte, poiché penso che ci sia più che voglio chiedere. – Hammerstein

+0

Ho sbagliato, in entrambi i casi si riceve un errore, ma nel secondo caso ne viene visualizzato uno diverso, 'errore CS0070: l'evento 'Program.Foo.Event2' può apparire solo sul lato sinistro di + = o - = (tranne quando usato all'interno del tipo 'Program.Foo') '. – user7116

9

Le proprietà di aggiunta/rimozione sono fondamentalmente della stessa logica di utilizzo delle proprietà set/get con altri membri. Consente di creare una logica aggiuntiva durante la registrazione per un evento e incapsula l'evento stesso.

Un buon esempio per PERCHE 'vorresti farlo, è interrompere il calcolo extra quando non è necessario (nessuno sta ascoltando l'evento).

Ad esempio, consente di dire gli eventi sono innescati da un timer, e non vogliamo che il timer di lavorare se nessuno è registrato per l'evento:

private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); 
private EventHandler _explicitEvent; 
public event EventHandler ExplicitEvent 
{ 
    add 
    { 
     if (_explicitEvent == null) timer.Start(); 
     _explicitEvent += value; 
    } 
    remove 
    { 
     _explicitEvent -= value; 
     if (_explicitEvent == null) timer.Stop(); 
    } 
} 

si sarebbe probabilmente desidera bloccare l'add/remove con un oggetto (ripensamento) ...