Ne kadar doğru bir olay işleyicisi kaldırmak için
Kod Gözden Geçirme, bu (basitleştirilmiş) kod parçası, bir olay işleyicisi kaydını buldum:
Fire -= new MyDelegate(OnFire);
Bu daha önce kayıtlı olan yeni bir temsilci yaratır çünkü olay işleyicisi kaydı değil diye düşündüm. Ama MSDN ben ararken bu tabiri kullanan bazı kod örnekleri buldum.
Bir deney başladım:
internal class Program
{
public delegate void MyDelegate(string msg);
public static event MyDelegate Fire;
private static void Main(string[] args)
{
Fire = new MyDelegate(OnFire);
Fire = new MyDelegate(OnFire);
Fire("Hello 1");
Fire -= new MyDelegate(OnFire);
Fire("Hello 2");
Fire -= new MyDelegate(OnFire);
Fire("Hello 3");
}
private static void OnFire(string msg)
{
Console.WriteLine("OnFire: {0}", msg);
}
}
Benim için sürpriz oldu, şu oldu:
Fire("Hello 1");
beklendiği gibi iki mesaj üretilir.Fire("Hello 2");
bir mesaj çıkardı.< / ^ br . Bunew
delegeler kaydını çalışıyor o beni ikna etti!Fire("Hello 3");
NullReferenceException
bir attı.< / ^ br . Kod hata ayıklamaFire
null
olay kaydı siliniyor sonra olduğunu gösterdi.
Olay işleyicileri ve temsilci için, derleyici sahne arkasında bir sürü kod oluşturur biliyorum. Ama ben hala benim akıl yanlış olduğunu anlamıyorum.
Neyi kaçırıyorum?
Ek soru: Fire
olaylar kayıtlı hiç bir zaman ** 16 yaşında olduğu için, her yerde bir olay harekete geçirilen sonuçlandırmak, null
karşı bir kontrol gereklidir.
CEVAP
C# derleyicisi işleyicisi çağırır bir olay çıkarırken Delegate.Combine
, bir olay işleyicisi Delegate.Remove
çağrı ekleme varsayılan uygulama:
Fire = (MyDelegate) Delegate.Remove(Fire, new MyDelegate(Program.OnFire));
Delegate.Remove
Çerçevesinde uygulanması MyDelegate
nesnenin kendisi bakmıyor, ama bu yöntem de temsilci (Program.OnFire
) anlamına gelir. Böylece, güvende varolan bir olay işleyicisi aboneliği ne zaman MyDelegate
yeni bir nesne oluşturmak için. Çünkü bu, C# derleyicisi kullanın bir steno sözdizimi (o üretir tam olarak aynı kodu sahne arkasında) ekleme/çıkarma olay işleyicileri: atlarsanız new MyDelegate
bölüm:
Fire = OnFire;
Fire -= OnFire;
Son temsilci olay işleyicisi kaldırıldığında, 27* *null döndürüyor. Bulduk, artırmadan önce boş karşı olayı kontrol etmek için önemlidir:
MyDelegate handler = Fire;
if (handler != null)
handler("Hello 3");
Geçici yerel bir değişkene atanmış diğer konuları olay işleyicileri aboneliği ile olası bir yarış durumu karşı savunmak için. (Yerel bir değişken için bir olay işleyicisi atama parçacığı güvenliği ile ilgili ayrıntılar için my blog post bakın.) Başka bir şekilde savunmaya karşı bu sorun oluşturmak için boş bir temsilci her zaman abone; bu süre kullanır biraz daha fazla bellek, olay işleyicisi ... asla boş (ve kod daha basit):
public static event MyDelegate Fire = delegate { };
Bir WordPress kullanmak en iyi bir şek...
Nasıl Net/JavaScript Olay İşleyicisi K...
Açıkça C olay işleyicileri kaldırmak i...
Ne kadar ulvi metin 2'de bir paketi ka...
Neden ve Nasıl Olay İşleyicisi bellek ...