Specyfikacja C# jawnie stwierdza (IIRC), że jeśli masz dwie anonimowe funkcje (metody anonimowe lub wyrażenia lambda), może on (ale nie musi) tworzyć równorzędnych delegatów z tego kodu. (Dwóch delegatów są równe, jeżeli mają równe cele i odnoszą się do tych samych metod.)
Aby mieć pewność, że trzeba pamiętać instancji delegata użyty:
EventHandler handler = (s, e) => MessageBox.Show("Woho");
button.Click += handler;
...
button.Click -= handler;
(nie mogę znajdź odpowiedni fragment specyfikacji, ale zdziwiłbym się, gdyby kompilator C# agresywnie próbował stworzyć równych delegatów. Z pewnością nie byłoby rozsądnie polegać na nim.)
Jeśli nie chcesz robić to, musisz wyodrębnić metodę:
public void ShowWoho(object sender, EventArgs e)
{
MessageBox.Show("Woho");
}
...
button.Click += ShowWoho;
...
button.Click -= ShowWoho;
Jeśli chcesz utworzyć procedurę obsługi zdarzeń, która usuwa się za pomocą wyrażenia lambda, jest nieco trudniejsza - musisz odwołać się do delegata w samym wyrażeniu lambda, a nie możesz tego zrobić za pomocą prostego polecenia "zadeklaruj lokalny zmienna i przypisanie jej za pomocą wyrażenia lambda ", ponieważ wtedy zmienna nie jest definitywnie przypisana. Zazwyczaj to obejść poprzez przypisanie wartości null do pierwszej zmiennej:
EventHandler handler = null;
handler = (sender, args) =>
{
button.Click -= handler; // Unsubscribe
// Add your one-time-only code here
}
button.Click += handler;
Niestety to nie jest nawet łatwo ująć to w sposób, ponieważ zdarzenia nie są równo reprezentowane. Najbliższy można przyjść byłoby coś takiego:
button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) =>
{
// One-time code here
}, handler => button.Click -= handler);
nawet to byłoby trudne do wdrożenia w ciągu Delegates.AutoUnsubscribe
bo trzeba by utworzyć nowy EventHandler
(co byłoby po prostu ogólny typ argument). Do zrobienia, ale niechlujny.
Zobacz tutaj: http://stackoverflow.com/questions/183367 –
Czy próbowałeś operatora - =? – Maciek
@Svish: lambda jest zasadniczo anonimową metodą. – dtb