2010-01-12 18 views
46

Gerçekten işe yarayıp yaramadığını merak ediyordum?Adsız Olay İşleyicisi Ekleme ve Kaldırma

private void RegisterKeyChanged(T item) 
{ 
    item.OnKeyChanged += (o, k) => ChangeItemKey((T)o, k); 
} 

private void UnRegisterKeyChanged(T item) 
{ 
    item.OnKeyChanged -= (o, k) => ChangeItemKey((T)o, k); 
} 

Derleyici olay işleyicilerinin aynı olduğunu nasıl biliyor? Bu bile tavsiye edilir mi?

+0

olası çift (https://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c-sharp) –

cevap

55

bu bahsediyor bir MSDN sayfa vardır: Özellikle

How to Subscribe to and Unsubscribe from Events

Not: [sic] aboneliğinizi iptal etmek olmayacaksa

bir olay daha sonra şunları yapabilirsiniz ek atama işlecini (+ =) için olayına anonim bir yöntem ekleyin.

Ve ayrıca:

onu abone olmak isimsiz fonksiyonu kullanıldığında eğer kolayca olay aboneliğini iptal edemez fark etmek önemlidir. Bu senaryoya göre aboneliğinden çıkmak, olaya abone bir temsilci değişkeninde anonim yöntemi depolamak ve sonra olay için temsilci eklemeye koduna geri dönmek için gereklidir. Genel olarak, size kodunda daha ileri noktada gelen olay aboneliğini zorunda kalacak eğer etkinliklere abone olmak için anonim işlevlerini kullanmayın önerilir.

+0

Yani, temelde OP'de ne olduğu varsayılan olarak çalışmıyor? Abonelik noktasında saklanmadığı takdirde, anonim temsilcisinin abonelikten çıkmak neredeyse imkansız olduğu anlamına mı geliyor? –

+0

Açıkçası, evet. –

1

Delegate.Equality belgesine bakarsanız, bunların referansla karşılaştırılmadığını öğrenirsiniz.

3

Bunun işe yarayacağına inanmıyorum. Bir etkinlikten gerçekten kaydını silmeniz gerekiyorsa, daha sonra anonim delege yerine kayıt yapamayacağınız açık bir olay işleyicisini belirtmeniz gerekir.

2

Bu işe yaramayacaktır Korkarım ki, bildirdiğiniz iki lambda ifadesi (ve delegeler) aslında farklı nesnelerdir ve farklı referanslar döndürür. Bu nedenle, işleyicinin kaldırılması (-=) her zaman başarısız olur.

Bu sorunun genel çözümü (işleyiciyi kaldırmanız gerektiğinde), lamba ifadesini uygun bir yöntemle yeniden düzenlemektir. Bir alternatif, olay işleyicisi temsilcisi için bir sınıf değişkenini korumak ve bunu bir hayranı olmamasına rağmen, ekleyip kaldırmaktır. (Bir şey varsa, sadece normal bir yöntem oluşturmaktan daha fazla güçlük çeker.)

+0

Not, Reed Copsey'in yaptığım gibi aynı çözümü önerdiği adresinde de oldukça benzer bir soru ve cevap var. . – Noldorin

5

Bir olay işleyicisinin aboneliğini iptal etmeniz gerekirse, somut bir temsilci için kesin bir başvuru yapmanız gerekir. Delegate.Equality'a bakıldığında, delegelerin sadece referans eşitliği kullanılarak değil, anonim temsilciler için önemli olmadığını göreceksiniz.

Anonim delege için, derleyici (temelde), temsilci gövdeleri aynı olsa bile, her bir anonim delege için yeni bir "anonim olmayan" temsilci oluşturur. Bu nedenle çerçeve, verdiğiniz kod örneğini kullandığınızda abonelikten çıkma yetkisini bulamaz.

8

ilgilenen herkes, ekleyebilir ve bu

public class Musician 
{ 
    public void TuneGuitar() 
    { 
     Metronome metronome = new Metronome(); 

     EventHandler<EventArgs> handler = null; 
     handler = (sender, args) => 
     { 
      // Tune guitar 
      // ... 

      // Unsubscribe from tick event when guitar sound is perfect 
      metronome.Tick -= handler; 
     }; 

     // Attach event handler 
     metronome.Tick += handler; 
    } 
} 

public class Metronome 
{ 
    event EventHandler<EventArgs> Tick; 
} 

UPDATE gibi anonim bir olay işleyicisi kaldırmak için: C# biz böylece TuneGuitar yöntem artık olarak yazılabilir local functions için desteklere sahip 7.0:

public void TuneGuitar() 
{ 
    Metronome metronome = new Metronome(); 

    void handler = (object sender, EventArgs args) => 
    { 
     // Tune guitar 
     // ... 

     // Unsubscribe from tick event when guitar sound is perfect 
     metronome.Tick -= handler; 
    }; 

    // Attach event handler 
    metronome.Tick += handler; 
} 
[C# iptal et anonim yöntem] arasında
İlgili konular