C# Delegates ve Events: Olay Tabanlı Programlamanın Gücü
C# programlama dilinde esnek ve genişletilebilir uygulamalar geliştirmek için Delegates (Temsilciler) ve Events (Olaylar) kritik öneme sahip yapılardır. Bu makale, C# dilinde bu iki güçlü kavramın ne olduğunu, nasıl kullanıldığını, birbirlerinden farklarını ve modern C# geliştirme süreçlerinde nasıl etkin bir şekilde uygulanabileceğini detaylı bir şekilde ele alacaktır.
Delegates Nedir?
Delegates, C# dilinde metotlara referans tutabilen, tip güvenli bir işaretçi görevi gören özel bir veri tipidir. Kısacası, bir metodu bir değişken gibi atayabilir, parametre olarak geçirebilir veya bir koleksiyonda saklayabilirsiniz. Bu, fonksiyonel programlama prensiplerine yakın bir esneklik sağlar ve olay tabanlı programlamanın temelini oluşturur.
Delegate Kavramı
Delegate, belirli bir imzaya (parametre tipleri ve dönüş tipi) sahip metotları temsil eden bir türdür. Bir delegate tanımladığınızda, aslında bu imzaya uyan herhangi bir metodu işaret edebilecek bir “şablon” oluşturmuş olursunuz. Bu sayede, hangi metodun çağrılacağını çalışma zamanında belirleyebilir ve kodunuzu daha dinamik hale getirebilirsiniz.
Neden Delegate Kullanmalıyız?
Delegates, özellikle bir metodun ne zaman veya hangi koşullar altında çağrılacağını bilmediğimiz durumlarda veya bir metodun başka bir metoda parametre olarak geçirilmesi gerektiğinde çok kullanışlıdır. Callback (geri çağırma) mekanizmaları, olay işleme ve çoklu yayın (multicast) senaryoları delegates ile kolayca uygulanabilir. Bu, kod tekrarını azaltır ve daha modüler bir tasarım sağlar.
Delegate’lerin Temel Yapısı
Bir delegate, delegate anahtar kelimesiyle tanımlanır. Tanımı, bir metot imzasına benzer: dönüş tipi, delegate adı ve parametre listesi. Örneğin, void döndüren ve bir string parametresi alan bir metodu temsil eden bir delegate şöyle tanımlanabilir:
public delegate void MesajGosterici(string mesaj);
Bu tanım, MesajGosterici adında bir delegate tipi oluşturur. Bu tip, void döndüren ve tek bir string parametresi alan herhangi bir metodu temsil edebilir.
Delegate Tanımlama ve Kullanım
Delegates, programlamada esneklik sağlayarak, çalışma zamanında hangi metodun çağrılacağına karar verme imkanı sunar. Bu bölüm, bir delegate'in nasıl tanımlandığını, bir metoda nasıl atandığını ve nasıl çağrıldığını detaylı örneklerle açıklar.
Delegate Tanımlama Sözdizimi
Delegate tanımlaması, bir metot imzası gibi yapılır, ancak başına delegate anahtar kelimesi eklenir. Genel sözdizimi şöyledir:
[erişim_belirleyici] delegate [dönüş_tipi] [DelegateAdı]([parametre_listesi]);
Örnek olarak, iki tam sayıyı alıp bir tam sayı döndüren bir delegate tanımlayalım:
public delegate int HesaplamaDelegate(int a, int b);
Delegate Nesnesi Oluşturma
Tanımlanan delegate tipi, artık bir sınıf gibi kullanılabilir. Bir delegate nesnesi oluşturmak için, delegate tipini ve bu tipe uygun imzaya sahip bir metodu belirtmeniz gerekir. Metot, statik veya örnek metot olabilir.
public class Hesaplayici
{
public int Topla(int x, int y) { return x + y; }
public int Carp(int x, int y) { return x * y; }
}
// Delegate nesnesi oluşturma
Hesaplayici hesaplayici = new Hesaplayici();
HesaplamaDelegate toplayici = new HesaplamaDelegate(hesaplayici.Topla);
HesaplamaDelegate carpan = hesaplayici.Carp; // Daha kısa sözdizimi (C# 2.0 sonrası)
Delegate Çağırma
Bir delegate nesnesi, tıpkı bir metot gibi çağrılabilir. Delegate'i çağırdığınızda, delegate'in işaret ettiği metot veya metotlar çalıştırılır.
int sonucToplama = toplayici(5, 3); // Topla metodu çağrılır
Console.WriteLine($"Toplama Sonucu: {sonucToplama}"); // Çıktı: 8
int sonucCarpma = carpan(5, 3); // Carp metodu çağrılır
Console.WriteLine($"Çarpma Sonucu: {sonucCarpma}"); // Çıktı: 15
Örnek Uygulama
Aşağıdaki örnek, bir delegate'in farklı metotları nasıl temsil edebileceğini ve çalışma zamanında nasıl kullanılabileceğini gösterir:
using System;
public delegate void YaziciDelegate(string metin);
public class Program
{
public static void KonsolaYaz(string mesaj)
{
Console.WriteLine($"Konsol: {mesaj}");
}
public static void HataGoster(string hataMesaji)
{
Console.Error.WriteLine($"HATA: {hataMesaji}");
}
public static void Main(string[] args)
{
YaziciDelegate yazici;
// KonsolaYaz metodunu temsil et
yazici = KonsolaYaz;
yazici("Merhaba Dünya!");
// HataGoster metodunu temsil et
yazici = HataGoster;
yazici("Bir hata oluştu!");
// Anonim metot veya lambda ifadesi ile de kullanılabilir
yazici = (m) => Console.WriteLine($"Lambda Yazıcı: {m}");
yazici("Lambda ile yazıldı.");
}
}
Multicast Delegates (Çoklu Yayın Delegeleri)
Delegates'in en güçlü özelliklerinden biri, birden fazla metodu aynı anda çağırabilme yeteneğidir. Bu özelliğe "Multicast Delegates" veya "Çoklu Yayın Delegeleri" denir. Bu sayede, tek bir delegate çağrısı ile birden fazla işlevi tetikleyebilirsiniz.
Birden Fazla Metodu İlişkilendirme
Bir delegate nesnesine birden fazla metot eklemek için + veya += operatörleri kullanılır. Bu, delegate'in bir "çağırma listesi" oluşturmasını sağlar. Çağırma listesindeki metotlar, delegate çağrıldığında sırayla yürütülür.
public delegate void BenimDelegate(string mesaj);
public class Bildirimci
{
public static void EmailGonder(string msg) { Console.WriteLine($"Email gönderildi: {msg}"); }
public static void SMSGonder(string msg) { Console.WriteLine($"SMS gönderildi: {msg}"); }
public static void LogYaz(string msg) { Console.WriteLine($"Log yazıldı: {msg}"); }
}
public class Program
{
public static void Main(string[] args)
{
BenimDelegate multicastDelegate = null;
multicastDelegate += Bildirimci.EmailGonder;
multicastDelegate += Bildirimci.SMSGonder;
multicastDelegate += Bildirimci.LogYaz;
multicastDelegate("Yeni bir işlem tamamlandı!");
}
}
Yukarıdaki örnekte, multicastDelegate çağrıldığında sırasıyla EmailGonder, SMSGonder ve LogYaz metotları çalışacaktır.
Delegate Zincirleme
Metotları bir delegate'e ekleyebildiğimiz gibi, - veya -= operatörlerini kullanarak çağrı listesinden metotları çıkarabiliriz. Bu, delegate zincirini dinamik olarak yönetmemizi sağlar.
// Önceki örnekten devam...
multicastDelegate -= Bildirimci.SMSGonder; // SMSGonder'i listeden çıkar
Console.WriteLine("\nSMS gönderimi iptal edildi:");
multicastDelegate("Önemli bir duyuru!");
Bu durumda, sadece EmailGonder ve LogYaz metotları çalışacaktır.
Kullanım Senaryoları
Multicast delegates, özellikle olay işleme mekanizmalarının temelini oluşturur. Bir olay meydana geldiğinde, bu olaya abone olan tüm metotların otomatik olarak çağrılmasını sağlar. Ayrıca, bir işlemi tamamladıktan sonra birden fazla farklı eylemi (örneğin, loglama, bildirim gönderme, veritabanı güncelleme) tetiklemek için de kullanılabilir.
Events Nedir?
Events (Olaylar), C# dilinde bir nesnenin belirli bir eylem gerçekleştirdiğini veya durumunun değiştiğini diğer nesnelere bildirmek için kullanılan özel bir delegate türüdür. Olaylar, Publisher-Subscriber (Yayıncı-Abone) tasarım deseninin C# dilindeki somut bir uygulamasıdır ve gevşek bağlı sistemler oluşturmanın anahtarıdır.
Olay Tabanlı Programlama
Olay tabanlı programlama, bir programın akışının olaylar tarafından belirlendiği bir paradigmada çalışır. Bir düğmeye tıklama, bir veri yükleme işlemi veya bir dosyanın kaydedilmesi gibi eylemler birer olaydır. Program, bu olaylara yanıt veren kod parçacıkları (olay işleyicileri) yazarak tepki verir. Events, bu olay işleyicilerini yönetmek için güvenli ve standart bir yol sunar.
Publisher-Subscriber Deseni
Events, Publisher-Subscriber desenini uygular:
* Publisher (Yayıncı): Olayı fırlatan (raise eden) nesnedir. Olayın ne zaman gerçekleştiğini ve hangi verileri taşıdığını bilir, ancak olaya kimin abone olduğunu veya nasıl işleneceğini bilmez.
* Subscriber (Abone): Olayı dinleyen ve olaya yanıt veren nesnelerdir. Olay meydana geldiğinde belirli bir eylemi gerçekleştirirler. Abone, olaya abone olur ve işleyicisini sağlar.
Bu ayrım, yayıncı ve abone arasında güçlü bir bağımlılık olmamasını sağlar, bu da kodun daha modüler ve bakımı kolay olmasını sağlar.
Event'lerin Avantajları
* Gevşek Bağlılık: Yayıncı ve abone arasında doğrudan bir bağımlılık yoktur. Bu, bir bileşenin diğerini etkilemeden değiştirilebileceği anlamına gelir.
* Kapsülleme: Events, delegate'lerin dışarıdan doğrudan çağrılmasını engeller. Sadece sınıfın içinden olay fırlatılabilir. Bu, kontrolü ve güvenliği artırır.
* Esneklik: Birden fazla abone, aynı olaya yanıt verebilir. Yeni aboneler kolayca eklenebilir veya çıkarılabilir.
* Standartlaşma: C# olayları, EventHandler ve EventArgs gibi standart desenler kullanarak tutarlı bir olay işleme mekanizması sağlar.
Event Tanımlama ve Kullanım
Events, C# dilinde event anahtar kelimesi kullanılarak tanımlanır ve genellikle bir delegate tipi ile ilişkilendirilir. Bu bölüm, bir event'in nasıl tanımlandığını, fırlatıldığını ve abone olunup çıkıldığını detaylı örneklerle açıklar.
Event Tanımlama Sözdizimi
Bir event, event anahtar kelimesiyle ve ardından bir delegate tipi ve event adı ile tanımlanır.
public delegate void OlayIsleyici(object sender, EventArgs e); // Genellikle kullanılan standart delegate
public class MyPublisher
{
public event OlayIsleyici MyEvent; // MyEvent adında bir olay tanımlandı
}
Yaygın olarak kullanılan standart EventHandler delegate'i ve EventArgs sınıfı ile tanımlama şöyledir:
public class MyPublisher
{
public event EventHandler MyEvent; // Standart EventHandler delegate'i kullanıldı
}
Event Fırlatma (Raising an Event)
Bir event, sadece tanımlandığı sınıfın içinden fırlatılabilir. Olayı fırlatmak, aslında event ile ilişkili delegate'i çağırmak anlamına gelir. Fırlatmadan önce, event'in null olup olmadığını kontrol etmek iyi bir pratiktir, çünkü hiçbir abone yoksa NullReferenceException hatası alabilirsiniz.
public class MyPublisher
{
public event EventHandler MyEvent;
public void DoSomething()
{
Console.WriteLine("İşlem yapılıyor...");
// Event'i fırlat
OnMyEvent(EventArgs.Empty); // Eğer özel veri yoksa EventArgs.Empty kullanılır
}
// Olay fırlatma metodunu kapsüllemek için Protected Virtual metot deseni
protected virtual void OnMyEvent(EventArgs e)
{
MyEvent?.Invoke(this, e); // Null kontrolü ve event'i fırlatma
}
}
MyEvent?.Invoke(this, e); ifadesi, MyEvent delegate'i null değilse Invoke metodunu çağırır. this parametresi, olayı fırlatan nesneyi (yayıncıyı) temsil ederken, e parametresi olayla ilgili verileri taşır.
Event'e Abone Olma ve Abonelikten Çıkma
Diğer sınıflar veya nesneler, bir event'e += operatörünü kullanarak abone olabilirler. Abonelikten çıkmak için ise -= operatörü kullanılır. Bu, multicast delegates'teki metot ekleme/çıkarma işlemine benzer.
public class MySubscriber
{
public void HandleMyEvent(object sender, EventArgs e)
{
Console.WriteLine("Abone: MyEvent olayı işlendi!");
MyPublisher publisher = sender as MyPublisher;
if (publisher != null)
{
Console.WriteLine($"Abone: Olayı fırlatan: {publisher.GetType().Name}");
}
}
}
public class Program
{
public static void Main(string[] args)
{
MyPublisher publisher = new MyPublisher();
MySubscriber subscriber = new MySubscriber();
// Event'e abone ol
publisher.MyEvent += subscriber.HandleMyEvent;
publisher.DoSomething(); // Olayı fırlatacak
// Event'ten abonelikten çık
publisher.MyEvent -= subscriber.HandleMyEvent;
Console.WriteLine("\nAbonelikten çıkıldı. Tekrar işlem yapılıyor...");
publisher.DoSomething(); // Bu sefer abone metodu çağrılmayacak
}
}
Bu örnekte, MySubscriber sınıfı MyPublisher'ın MyEvent olayına abone olur, olay fırlatıldığında HandleMyEvent metodu çalışır ve ardından abonelikten çıkarak bir sonraki olay fırlatmasında tepki vermez.
Standart Event Desenleri
C# dilinde olayları tanımlarken ve kullanırken belirli bir desen (pattern) izlenmesi önerilir. Bu desen, EventHandler delegate'i ve EventArgs sınıfının kullanımıyla tutarlı ve anlaşılır bir yapı sağlar.
EventHandler ve EventArgs
* EventHandler Delegate'i: .NET Framework, olaylar için standart bir delegate tipi olan EventHandler'ı sağlar. Bu delegate, void döndürür ve iki parametre alır:
* object sender: Olayı fırlatan nesneye bir referanstır.
* EventArgs e: Olayla ilgili verileri içeren bir nesnedir. Eğer olay herhangi bir özel veri taşımıyorsa EventArgs.Empty kullanılabilir.
public delegate void EventHandler(object sender, EventArgs e);
* EventHandler Generic Delegate: Eğer olayınız özel veri taşıyorsa, EventHandler generic delegate'ini kullanmak daha iyidir. Burada TEventArgs, EventArgs sınıfından türetilmiş özel bir sınıf olmalıdır.
public delegate void EventHandler(object sender, TEventArgs e) where TEventArgs : EventArgs;
Custom EventArgs Sınıfları
Olayınızın, olayı işleyecek abonelere özel bilgiler iletmesi gerektiğinde, EventArgs sınıfından türeyen kendi özel sınıfınızı oluşturmalısınız.
public class CustomDataEventArgs : EventArgs
{
public string Message { get; }
public DateTime EventTime { get; }
public CustomDataEventArgs(string message, DateTime eventTime)
{
Message = message;
EventTime = eventTime;
}
}
public class DataProcessor
{
// Generic EventHandler kullanıldı
public event EventHandler DataProcessed;
public void ProcessData(string data)
{
Console.WriteLine($"Veri işleniyor: {data}");
// Olayı fırlatırken özel veri iletiliyor
OnDataProcessed(new CustomDataEventArgs($"'{data}' verisi işlendi.", DateTime.Now));
}
protected virtual void OnDataProcessed(CustomDataEventArgs e)
{
DataProcessed?.Invoke(this, e);
}
}
public class DataConsumer
{
public void HandleDataProcessed(object sender, CustomDataEventArgs e)
{
Console.WriteLine($"Tüketici: Olay fırlatıldı: '{e.Message}' - Zaman: {e.EventTime}");
}
}
public class Program
{
public static void Main(string[] args)
{
DataProcessor processor = new DataProcessor();
DataConsumer consumer = new DataConsumer();
processor.DataProcessed += consumer.HandleDataProcessed;
processor.ProcessData("Örnek Veri 123");
processor.DataProcessed -= consumer.HandleDataProcessed;
}
}
Genel Kullanım İpuçları
* Olay fırlatma metodunu On[EventAdı] şeklinde adlandırın (örn. OnDataProcessed).
* Bu metodu protected virtual olarak tanımlayın, böylece türetilmiş sınıflar olayı fırlatma davranışını özelleştirebilir.
* Olayı fırlatmadan önce null kontrolü yapın (EventName?.Invoke(...)).
* Olay işleyicilerinde uzun süreli veya bloke edici işlemler yapmaktan kaçının, çünkü bu yayıncıyı kilitleyebilir.
* Abonelikten çıkmayı unutmayın, özellikle uzun ömürlü nesnelerde bellek sızıntılarını önlemek için.
Delegates ve Events Arasındaki Farklar
Delegates ve Events birbirine sıkıca bağlı kavramlar olsa da, kullanım amaçları ve sundukları güvenlik/kapsülleme açısından önemli farklara sahiptirler. Bu farkları anlamak, doğru senaryoda doğru yapıyı kullanmak için kritik öneme sahiptir.
Erişim Kısıtlamaları
* Delegates: Bir delegate nesnesi, tanımlandığı yerden ve erişim belirleyicisine göre herhangi bir yerden doğrudan çağrılabilir. Bu, delegate'in referansını tutan herkesin delegate'i tetikleyebileceği anlamına gelir.
* Events: Bir event anahtar kelimesiyle tanımlandığında, olay sadece tanımlandığı sınıfın içinden fırlatılabilir. Dışarıdan sadece += ve -= operatörleri ile abone olunabilir veya abonelikten çıkılabilir. Doğrudan event() şeklinde çağırmak mümkün değildir. Bu, olayların dışarıdan kötüye kullanılmasını veya yanlışlıkla tetiklenmesini engeller.
Kullanım Amaçları
* Delegates: Daha genel amaçlıdır. Callback mekanizmaları, metotları parametre olarak geçirme, LINQ sorgularında veya ThreadPool gibi yapılarda metotları temsil etme gibi geniş bir yelpazede kullanılır.
* Events: Özellikle Publisher-Subscriber deseni için tasarlanmıştır. Bir nesnenin durum değişikliğini veya bir eylemi diğer nesnelere güvenli ve kapsüllenmiş bir şekilde bildirmesi gerektiğinde kullanılır.
Güvenlik ve Kapsülleme
Aşağıdaki tablo, Delegates ve Events arasındaki temel farkları özetlemektedir:
| Özellik | Delegate | Event |
|---|---|---|
| Tanım | Metotlara referans tutan tip güvenli işaretçi. | Özel bir delegate türü, event anahtar kelimesiyle tanımlanır. |
| Çağırma | Herhangi bir yerden doğrudan çağrılabilir (erişim belirleyiciye göre). | Sadece tanımlandığı sınıfın içinden fırlatılabilir. |
| Abonelik/İptal | =, +=, -= operatörleri ile referans atama ve zincirleme. |
Sadece += (abone olma) ve -= (abonelikten çıkma) operatörleri ile. |
| Kapsülleme | Düşük kapsülleme, referansı olan herkes metotları çağırabilir. | Yüksek kapsülleme, sadece yayıncı olayı fırlatabilir. |
| Amaç | Callback'ler, dinamik metot çağırma, LINQ, Threading. | Olay tabanlı programlama, Publisher-Subscriber deseni. |
Özetle, bir delegate, bir metot işaretçisi iken; bir event, bu metot işaretçisinin (delegate'in) güvenli ve kontrollü bir şekilde dışarıya açılan bir arayüzüdür. Event'ler, delegate'ler üzerine inşa edilmiş daha yüksek seviyeli bir soyutlamadır.
Anonim Metotlar, Lambda İfadeleri ve Events
Modern C# sürümleri, anonim metotlar ve özellikle lambda ifadeleri sayesinde delegate ve event kullanımını daha da basitleştirmiş ve okunabilir hale getirmiştir. Bu yapılar, kısa süreli veya tek kullanımlık delegate'ler ve event işleyicileri tanımlamak için idealdir.
Anonim Metotlarla Event Aboneliği
C# 2.0 ile tanıtılan anonim metotlar, isimsiz metot blokları oluşturarak delegate'leri daha kolay tanımlamamızı sağladı. Özellikle olay işleyicileri için, ayrı bir metot tanımlamak yerine doğrudan abone olurken kodu yazmaya olanak tanıdı.
public class Timer
{
public event EventHandler Tick;
public void Start()
{
Console.WriteLine("Timer başladı.");
Tick?.Invoke(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main(string[] args)
{
Timer timer = new Timer();
// Anonim metot ile event'e abone olma
timer.Tick += delegate(object sender, EventArgs e)
{
Console.WriteLine("Anonim metot: Zamanlayıcı tıklandı!");
};
timer.Start();
}
}
Lambda İfadelerinin Gücü
C# 3.0 ile gelen lambda ifadeleri, anonim metotların daha kısa ve daha güçlü bir versiyonudur. Özellikle LINQ sorgularında yaygın olarak kullanılmalarının yanı sıra, event aboneliklerinde de oldukça popülerdirler.
// Önceki Timer örneği üzerinden devam edelim
public class Program
{
public static void Main(string[] args)
{
Timer timer = new Timer();
// Lambda ifadesi ile event'e abone olma
timer.Tick += (sender, e) =>
{
Console.WriteLine("Lambda: Zamanlayıcı tıklandı!");
Console.WriteLine($"Olayı fırlatan: {sender.GetType().Name}");
};
timer.Start();
}
}
Lambda ifadeleri, özellikle tek satırlık veya kısa kod bloklarına sahip olay işleyicileri için kodun okunabilirliğini önemli ölçüde artırır. Parametre tipleri genellikle derleyici tarafından çıkarılabilir, bu da kodu daha da kısaltır.
Modern C# Yaklaşımları
Modern C# geliştirme süreçlerinde, olay aboneliklerinde genellikle lambda ifadeleri tercih edilir. Bu, kodun daha temiz, daha özlü ve daha işlevsel olmasını sağlar. Özellikle async/await ile birlikte kullanıldığında, asenkron olay işleyicilerini tanımlamak da oldukça kolaylaşır.
Ancak, bir lambda ifadesi veya anonim metot ile abone olunduğunda, abonelikten çıkmak için aynı referansı kullanmak gerekir. Eğer lambda ifadesi doğrudan += içinde tanımlanıyorsa, aynı lambda ifadesini -= ile kullanmak mümkün olmayabilir, çünkü her lambda ifadesi derlendiğinde farklı bir anonim metot nesnesi oluşturulur. Bu durumda, lambda ifadesini bir değişkene atayıp o değişken üzerinden abone olmak ve abonelikten çıkmak en güvenli yoldur.
// Lambda ifadesini bir değişkene atayarak abonelikten çıkma
EventHandler handler = (sender, e) => Console.WriteLine("Abonelikten çıkılabilen lambda!");
timer.Tick += handler;
timer.Start();
timer.Tick -= handler; // Şimdi abonelikten çıkılabilir
Bu yaklaşım, bellek sızıntılarını önlemek ve olay aboneliklerini doğru bir şekilde yönetmek için önemlidir.
Sonuç
C# Delegates ve Events, modern ve esnek uygulamalar geliştirmek için vazgeçilmez yapı taşlarıdır. Delegates, metotlara referans tutarak dinamik kod yürütme ve callback mekanizmaları sağlarken, Events bu delegate'ler üzerine inşa edilmiş, Publisher-Subscriber desenini uygulayan güvenli ve kapsüllenmiş bir olay işleme mekanizması sunar. Bu iki kavramın doğru anlaşılması ve etkin bir şekilde kullanılması, daha modüler, bakımı kolay ve genişletilebilir C# uygulamaları yazmanın anahtarıdır. Anonim metotlar ve lambda ifadeleri gibi modern C# özellikleri ise bu yapıların kullanımını daha da kolaylaştırarak geliştirici verimliliğini artırmaktadır.
SSS (Sık Sorulan Sorular)
1. Delegate nedir ve ne işe yarar?
Delegate, C# dilinde metotlara referans tutabilen, tip güvenli bir işaretçi görevi gören özel bir veri tipidir. Bir metodu bir değişken gibi atayabilir, parametre olarak geçirebilir veya bir koleksiyonda saklayabilirsiniz. Callback mekanizmaları, olay işleme ve çoklu yayın (multicast) senaryolarında kullanılır.
2. Events neden Delegates üzerine inşa edilmiştir?
Events, aslında özel bir delegate türüdür. Delegate'ler, metot referanslarını tutma ve çağırma yeteneği sağlar. Events, bu delegate mekanizmasını kullanarak, yayıncı ve abone arasında kontrollü ve kapsüllenmiş bir iletişim kanalı oluşturur. event anahtar kelimesi, delegate'in dışarıdan doğrudan çağrılmasını engelleyerek güvenliği artırır.
3. Bir event'i nasıl fırlatırım (raise ederim)?
Bir event, sadece tanımlandığı sınıfın içinden fırlatılabilir. Genellikle On[EventAdı] şeklinde adlandırılan protected virtual bir metot içinde, event delegate'i null kontrolü yapılarak çağrılır: MyEvent?.Invoke(this, e);.
4. EventHandler ve EventHandler arasındaki fark nedir?
`
