2009-09-01 13 views
187

Possibili duplicati:
Unsubscribe anonymous method in C#
How do I Unregister ‘anonymous’ event handlerCome rimuovere un gestore di eventi lambda

recente ho scoperto che posso usare lambda per creare semplici gestori di eventi. Potrei ad esempio iscriversi ad un evento click come questo:

button.Click += (s, e) => MessageBox.Show("Woho"); 

Ma come si annullerebbe l'iscrizione?

+0

Vedere qui: http://stackoverflow.com/questions/183367 –

+0

Hai provato l'operatore - =? – Maciek

+1

@Svish: un lambda è essenzialmente un metodo anonimo. – dtb

risposta

267

La specifica C# indica esplicitamente (IIRC) che se si dispone di due funzioni anonime (metodi anonimi o espressioni lambda) può o non può creare delegati uguali da tale codice. (Due delegati sono uguali se hanno obiettivi uguali e si riferiscono agli stessi metodi.)

A dire il vero, avresti bisogno di ricordare l'istanza delegato si è utilizzato:

EventHandler handler = (s, e) => MessageBox.Show("Woho"); 

button.Click += handler; 
... 
button.Click -= handler; 

(non posso trovare il bit pertinente della specifica, ma sarei piuttosto sorpreso di vedere il compilatore C# in modo aggressivo cercare di creare uguali delegati. Sarebbe certamente imprudente affidarsi a questo.)

Se non si vuole fare che, è necessario estrarre un metodo:

public void ShowWoho(object sender, EventArgs e) 
{ 
    MessageBox.Show("Woho"); 
} 

... 

button.Click += ShowWoho; 
... 
button.Click -= ShowWoho; 

Se si desidera creare un gestore eventi che rimuove se stesso utilizzando un'espressione lambda, è leggermente più complicato - è necessario fare riferimento al delegato all'interno dell'espressione lambda stessa e non è possibile farlo con un semplice "dichiarare un locale" variabile e assegnarlo usando un'espressione lambda "perché quindi la variabile non è assegnata in modo definitivo. In genere si ottiene intorno a questo assegnando un valore nullo alla variabile prima:

EventHandler handler = null; 
handler = (sender, args) => 
{ 
    button.Click -= handler; // Unsubscribe 
    // Add your one-time-only code here 
} 
button.Click += handler; 

Purtroppo non è nemmeno facile racchiudendolo in un metodo, perché gli eventi non sono in modo pulito rappresentate. Il più vicino si potrebbe venire sarebbe qualcosa di simile:

button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) => 
{ 
    // One-time code here 
}, handler => button.Click -= handler); 

Anche questo sarebbe difficile da implementare entro Delegates.AutoUnsubscribe perché dovreste creare un nuovo EventHandler (che sarebbe solo un argomento di tipo generico). Fattibile, ma disordinato

+1

Esattamente, se si guarda all'interno dell'assieme compilato utilizzando Reflector, si noterà che il il compilatore ha creato un puntatore per te comunque quando usi lambda, è solo che non lo vedi in Visual Studio – Raffaeu

+1

@Raffaeu: chiamarlo un puntatore è un po 'fuorviante - non è un puntatore nel normale senso C# della parola . –

+2

Sì scuso, "i compilatori creeranno comunque la variabile del gestore" è meglio? :) – Raffaeu

Problemi correlati