2009-09-01 23 views
187

Olası çoğaltır kaldırmak için:
Unsubscribe anonymous method in C#
How do I Unregister ‘anonymous’ event handlernasıl bir lambda olay işleyicisi

Geçenlerde basit olay işleyicileri oluşturmak için lambdas kullanabilirsiniz keşfetti. Örneğin, şu gibi bir tıklama etkinliğine abone olabilirim:

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

Ancak nasıl bir abonelikten vazgeçersiniz?

+0

Bakın: http://stackoverflow.com/questions/183367 –

+0

- = Operatörü denediniz mi? – Maciek

+1

@Svish: Bir lambda aslında anonim bir yöntemdir. – dtb

cevap

267

C# belirtimi, iki anonim işleviniz (anonim yöntemler veya lambda ifadeleri) varsa, bu koddan eşit delegeler oluşturabileceğini veya oluşturmayacağını açıkça belirtir (IIRC). (Bunlar eşit hedeflere sahip ve aynı yöntemlerle ifade ederse delege eşittir.)

emin olmak için, kullandığınız temsilci oluşumu hatırlamak gerekir:

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

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

(Yapamam Spesifik bir bit türünü bulabilirim, ama C# derleyicisini agresif olarak eşit delegeler oluşturmaya çalışacağımı görmek beni hayrete düşürürdü. Kesinlikle buna güvenmemek gerekir.)

Eğer yapmak istemiyorsanız Bu, bir yöntemi ayıklamanız gerekir:

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

... 

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

Bir lambda ifadesi kullanarak kendini kaldıran bir olay işleyicisi oluşturmak istiyorsanız, biraz daha zorlayıcı - delege lambda ifadesinin kendisinde bakın ve bunu basit bir "yerel" ile bildiremezsiniz değişken ve bir lambda ifadesi kullanarak atayın "çünkü o zaman değişken kesinlikle atanmamış. Genellikle ilk değişkene boş değer atayarak bu sorunu olsun: olaylar temiz temsil edilmez çünkü

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

Ne yazık ki, bir yöntem haline bu saklanması bile kolay değil. Gelebildiğinize yakın gibi bir şey olurdu: Oluşturmak olurdu çünkü Delegates.AutoUnsubscribe içinde uygulamak zor olacağını bile

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

yeni EventHandler (sadece bir genel tür argümanı olurdu). Yapılabilir, ama dağınık.

+1

Tam olarak derlenmiş montajınızın içine Reflektör kullanarak bakarsanız, fark edeceksiniz. derleyici lambda kullandığınızda sizin için bir işaretçi yarattı, sadece Visual Studio – Raffaeu

+1

@Raffaeu içinde görmüyorsun: Bir işaretçi çağırmak biraz yanıltıcıdır - bu kelimenin normal C# anlamında bir işaretçi değil . –

+2

Evet özür dileriz, "Derleyiciler zaten işleyici değişkeni yaratacaktır" daha iyi mi? :) – Raffaeu

İlgili konular