Bir önceki yazıda yapıcı metotlardan bahsetmiştik. Bu yazıda ise yıkıcı metotları inceleyeceğiz. Bunlar bir nesne artık kullanımda olmadığında nesne bellekten temizlenmeden önce çalıştırılan metotlardır. Bu temizleme işlemini Garbage Collector (çöp toplayıcı) mekanizması yapar.

C# - Destructors (Yıkıcı Metotlar)

Yıkıcı metotlar çağrılabilen metotlar değildirler. Nesnenin kullanıldığı blok (küme parantezleri) sona erdiğinde çağrılırlar ve nesne hafızadan silinir. Yıkıcı metotların tıpkı yapıcı metotlar gibi geri dönüş tipleri yoktur. Yapıcı metotlardan farklı olarak parametre alamazlar. Yıkıcılar aşırı yüklenemez ve miras alınamazlar. Sadece sınıf içinde tanımlanabilirler.

Yıkıcıların erişim belirleyicisi yoktur. Tanımlanmadan önce isme ~ (tilda) ön eki getirilmelidir. Şimdi basitçe bir örnek yapalım ve yıkıcıların çalışma mantığına bir göz atalım.

class Uye
{
    public int No { get; set; }

    ~Uye()
    {
        Debug.WriteLine(this.No + ": Yok oluyorum...");
    }
}

Debug sınıfı ile yazılanlar output penceresinde görünürler. Eğer sizde yoksa menüden "View > Output" yolunu izleyerek ya da CTRL + W + O kombinasyonuna basarak açabilirsiniz. Debug sınıfını kullanabilmek için projenize System.Diagnostics kütüphanesini çağırmış olmalısınız.

Şimdi aşağıdaki gibi bir döngü yardımıyla birkaç tane nesne oluşturalım ve çıktı ekranını izleyelim.

for (int i = 0; i < 10; i++)
{
    Uye uye = new Uye();
    uye.No = i;
}
Console.ReadLine();

Programı çalıştırın ve output ekranını izleyin. Enter tuşuna basmadıkça (çünkü program ReadLine satırı yüzünden bekliyor) nesneler yok edilmeyecektir. Ne zaman ki Enter'a basarınız, göreceksiniz ki program kapanacak ve tüm nesneler yok edilecekler.

9: Yok oluyorum... 8: Yok oluyorum... 7: Yok oluyorum... 6: Yok oluyorum... 5: Yok oluyorum... 4: Yok oluyorum... 3: Yok oluyorum... 2: Yok oluyorum... 1: Yok oluyorum... 0: Yok oluyorum...

Son eklenen obje ilk önce yok edilmiş. Buradan nesnelerin LIFO sırasıyla yok edildiğini anlamış olduk. Yani bir nevi bir yığın yapısı kullanılıyor.

Yukarıdaki örnekte nesneler içinde bulundukları blok (Main) bitene kadar beklediler. İstersek bu işlemi kendimiz tetikleyebiliriz.

Debug.WriteLine("Nesneler üretiliyor...");

for (int i = 0; i < 10; i++)
{
    Uye uye = new Uye();
    uye.No = i;
}

GC.Collect();

Console.ReadLine();

Gördüğünüz üzere nesneler yok edilmek için Enter tuşuna basmamız beklenmedi. GC (Garbage Collector) sınıfı sayesinde temizleme işlemini manüel yaptık.

10: Yok oluyorum... 1: Yok oluyorum... 0: Yok oluyorum... 9: Yok oluyorum... 8: Yok oluyorum... 7: Yok oluyorum... 6: Yok oluyorum... 5: Yok oluyorum... 4: Yok oluyorum... 3: Yok oluyorum... 2: Yok oluyorum...

Çıktıya baktığımızda bu sefer temizleme işleminin daha raslantısal bir düzende yapıldığını görebiliriz.

Pratikte, eğer çok yoğun veri akışı olan büyük projelerde çalışmıyorsanız aslında pek karşınıza çıkacak şeyler değildir. Normalde temizleme işini Garbage Collector üstlenir ama yetersiz geldiği durumlar olabilir. Örneğin bir Thread havuzunu sonlandırabilir, açık dosyaları (stream) kapatabilir ya da veritabanı bağlantısını sonlandırabilirsiniz. Projenizde Windows API'leri gibi unmanaged kod kullandıysanız onları silebilirsiniz.