C# Delegate Nedir ? Nasıl Uygulanır ?

Sefa Can Pehlivan
4 min readAug 5, 2023

--

Oop’yi anlattıktan sonra yavaş yavaş desing patternleri anlatmayı düşünmüştüm fakat kodumuzun daha okunaklı daha temiz, kullanılabilir ve geliştirilebilir olmasında büyük bir etkiye sahip olan Delegate ve Event kavramlarını öne almaya karar verdim. Bu yazımda Delegate’i anlatacağım bir sonrakinde de Event’i anlatıp ikisinin arasındaki bağlantılara değineceğim.

Delegate Nedir ?

Delegate’i basitçe anlatmak gerekirse içerisinde fonksiyon veya fonksiyonları tutabilen yapılardır, örnek vermek gerekirse nasıl bir integer içinde tamsayı tutabiliyor ise delegate de içinde fonksiyon tutabilir yani delegatelerin değer tipi fonksiyondur.

Peki bu delegate’ler nerelerde ve nasıl kullanılır kısaca değinelim :

  • Eventler (Olaylar): Delegate’ler, eventleri temsil etmek için kullanılır. Bir sınıfta bir event tanımladığınızda, aslında bir delegate türünden bir event oluşturuyorsunuz. Diğer sınıflar bu olaya abone olabilir ve olay tetiklendiğinde bu abone fonksiyonlar çalışır.
  • Toplu İşlemler: Delegate’ler, birden çok işlemi kolayca uygulamanıza olanak tanır. Liste, dizi veya koleksiyonlardaki tüm öğeler için aynı işlemi uygulamak için delegate’leri kullanabilirsiniz.
  • Asenkron Programlama: Delegate’ler, çoklu iş parçacığı (thread) kullanarak asenkron işlemleri kolaylaştırır. Bir delegate, bir işlemi asenkron olarak başlatmak ve işlem tamamlandığında geri çağırma(Callback) fonksiyonu çalıştırmak için kullanılabilir.
  • Callback’ler: Bir fonksiyon, bir işlemi tamamladığında başka bir fonksiyonu geri çağırmak için delegate kullanabilirsiniz. Bu, özellikle bir işlem asenkron olarak gerçekleştiğinde ve sonucunun işlendiği başka bir fonksiyon olduğu durumlarda yaygındır.

Bu liste uzayıp gidebilir sadece bir kaç kullanım örneği vermek istedim örnekler arasında bilmediğiniz terimler var ise dert etmeyin bu yazıda sadece Delegate’i anlamaya odaklanın.

Delegate Nasıl Uygulanır ?

Delegate kullanmak için başlangıçta yapmamız gereken iki şey var, birincisi delegate’in kendisini tanımlamak, ikincisi delegate objesini oluşturmak.

Daha sonra bu delegate içine istediğimiz Fonsksiyonları += ifadesi ile eklemek. Evet artık delegate’imiz kullanıma hazır artık istediğimiz yerde onu çağırıp kullanabiliriz. Şimdi sizin için yazdığım örnek koda bakalım.

using UnityEngine;

// Delegate tanımı
public delegate void GameOverDelegate();

public class GameManager : MonoBehaviour
{
// GameOverDelegate objesini oluşturmak
public GameOverDelegate onGameOver;

// Fonksiyonlar
void StopTime()
{
Time.timeScale = 0f;
}

void OpenGameOverUI()
{
// Game Over UI'nı açma işlemleri
}

void PlayGameOverSound()
{
// Oyun kaybetme müziğini başlatma işlemleri
}

// Delegate'i oluşturulan fonksiyonlarla doldurmak
private void Start()
{
onGameOver += StopTime;
onGameOver += OpenGameOverUI;
onGameOver += PlayGameOverSound;
}
}

Bu örneği bir oyunun GameOver olması senaryosunu ele alarak yazdım ve size üstteki kodu parçalara bölerek adım adım anlatacağım.

ilk önce delegate’imizi tanımladık ve delegate objemizi oluşturduk.

Delegate tanımlaması şu şekildedir ilk önce access modifiers’ımızı ekliyoruz ben public yaptım, sonra “delegate” anahtar kelimesini ekliyoruz, ondan sonra delegate’in dönüş tipi(Return Type) daha sonra delegate’in ismi ve eğer eklemek istersek parantez içine parametre işlem bu kadar.

Burada özellikle değinmek istediğim bir nokta var, delegate’in dönüş tipini dikkatli ve önceden planlayarak ayarlamalısınız. Şimdi diyebilirsiniz dönüş tipi nedir diye, delegate’lerde dönüş tipi aslında fonksiyonlardaki dönüş tipi ile aynı şeydir nasıl’ki bir int dönüş tipine sahip fonksiyondan float döndüremiyorsak delegate’in dönüş tipi ne ise içine aldığı fonksiyonlarında dönüş tipi aynı olmalı yoksa kodumuz hata vericektir.Ben örneğimde void yani hiçbirşey döndürmeyen tipi kullandım.

// Delegate tanımı
public delegate void GameOverDelegate();
// GameOverDelegate objesini oluşturmak
public GameOverDelegate onGameOver;

Daha sonra 3 adet fonksiyon yazdım bu fonksiyonlar oyuncu oyunu kaybettiğinde gerçekleşmesini istediğim şeyler.

// Fonksiyonlar
void StopTime()
{
Time.timeScale = 0f;
}

void OpenGameOverUI()
{
// Game Over UI'nı açma işlemleri
}

void PlayGameOverSound()
{
// Oyun kaybetme müziğini başlatma işlemleri
}

Ve bu fonksiyonlarımı += kullanarak delegate’imin içine ekliyorum. peki çıkarmak istersem ne yapmam gerek diye soracak olursanız -= kullanarakta eklediğimiz fonksiyonu çıkarabilirsiniz.

// Delegate'i oluşturulan fonksiyonlarla doldurmak
private void Start()
{
onGameOver += StopTime;
onGameOver += OpenGameOverUI;
onGameOver += PlayGameOverSound;
}

Evet delegate’imizin içi fonskiyonlarımızla doldu kullanıma hazır şimdi kullanımı aşağıdaki örnekte inceleyelim.

public class Character : MonoBehaviour
{
private int health = 100;

// GameManager'ı referans alıyoruz
public GameManager gameManager;

// Karakterin canı azaldığında çağrılacak fonksiyon
public void DecreaseHealth(int amount)
{
health -= amount;
if (health <= 0)
{
// Delegate'i çağırıyoruz
gameManager?.onGameOver?.Invoke();
// Soru işareti null gelmesin diye yaptığım bir kontrol.
}
}
}

Burada karakterimizin can değerine bağlı olarak bir fonksiyon oluşturduk ve can değeri sıfıra indiğinde gameManager objesi üzerinden delegate’imizi çağırarak işlemlerimizi yaptırdık.

Buradaki kullanım yukarıda bahsettiğim “Toplu İşlemler” uygulamasına bir örnek oldu eğer burada delegate kullanmasaydık methodlarımızı tek tek çağırmamız gerekecekti. Ve eğer tek tek çağırmamız gerekseydi bizi etkileyecek dezavantajlar şunlar :

  • Kod kirliliği: oyun gameOver oldugunda 3 değil 30 fonksiyon’da çağırmamız gerekebilirdi ve bu şekilde kullanım her kullandıgımız yerde fazlaca kod kirliliği ve karmaşasına sebep olurdu.
  • Kodu Yönetmede Zorluk: diyelim oyunun gameOver olması birden çok yerde kullanılıyor her yere tek tek ilgili fonksiyonları eklerken bir anlık dalgınlık ile 1 tanesini eklemeyi unuttuk bu büyük bir sorun ortaya çıkarır veya proje geliştirilirken oyunun gameOver olması olayına 3 fonksiyon daha eklenecek delegate varken işlem kolay 3 fonksiyonu’da delegate’e ekleriz ve delegate’imizin olduğu heryere fonksiyonlar eklenmiş olur ama delegate kullanmazsak o fonksiyonların eklenmesi gereken yerleri tek tek bulup eksiksiz eklememiz gerekir bu da hem hata yapma şansımızı arttırır hem de bu çok oyalayıcı olduğundan dolayı proje bir yerden sonra yönetilemez hale gelir.

Düşündükçe aklımıza daha çok dezavantaj geleceğine eminim ama sanırım bu iki sebep bile delegate kullanmak için yeterli. Okuduğunuz için teşekkürler bir sonraki yazı Event’ler üzerine olacaktır.

--

--