Memik Yanık - Kişisel Web Sitesi Ana Sayfa | Hakkımda | Kitap Önerileri | Fotoğraflarım | RSS RSS | İletişim

Form Sınıfının Dispose Metodu


Visual Studio ile hazırladığınız projeye yeni bir form eklediğinizde forma ait Designer.cs dosyasında aşağıdaki gibi bir Dispose() metodu hazırlanmaktadır. Başka bir deyişle Form sınıfı kaynaklı Dispose() metodu override edilmektedir. Aşağıda verilen kodu incelerseniz “Form1” için Visual Studio tarafından override edilen Dispose() metodunun geriye değer göndermediğini ve bool bir parametreye sahip olduğunu görürsünüz. Metotta ilk olarak “disposing” adlı bool parametrenin true olup olmadığı araştırılmaktadır. disposing adı verilen parametre true ise bu kez IContainer tipindeki components değişkenin null olup olmadığına bakılmaktadır.



Hem Dispose() metodunun parametresi true hem de IContainer tipindeki değişkenin içeriği null’dan farklı ise Dispose() metodunun parametresiz versiyonu components adlı IContainer tipindeki değişkene uygulanmaktadır. Tam bu noktada bazılarınızın aklına bu components adındaki ve IContainer tipindeki değişkenin işlevi nedir sorusu gelmiş olabilir.

Hatta Visual Studio ile hazırlanan projeleri didik didik etseniz bile bu components adındaki değişkenin hiç kullanılmadığını ve null olarak kaldığını görürsünüz. Bu nedenle birçok kaynakta “components” adlı bu değişkenden hiç söz edilmez. Aslında sizler de bu değişkenle ilgilenmeyebilirsiniz. Madem Microsoft’un programcıları Override ettikleri Dispose() metodu içinde bu değişkenin null olup olmadığını araştırıyorlar biraz üzerinde duralım. Bu amaçla üzerinde çalıştığım projenin formunun Load olayını temsil eden metodu aşağıdaki gibi düzenledim. 

private void Form1_Load(object sender, EventArgs e)
 {
   TextBox Text1 = new TextBox();
   Button Dugme1 = new Button();
 }

.NET Framework ile gelen 2 sınıfın örneğinin alındığı bu metotta hazırlanıp formun Controls koleksiyonuna eklenmeyen bu 2 nesne Form1_Load() metodunun sonuna gelindiğinde her ikisi de gereksiz nesne durumuna düşerler. Bu şartlarda GC mekanizması uygun gördüğü bir zamanda bu 2 nesneyi bellekten temizler. Bu 2 nesne formun Controls koleksiyonuna eklenseydiler form kapatıldığında ikisi de otomatik olarak dispose edilirdi. Madem bu 2 nesneyi Controls koleksiyonuna eklemedik o halde form kapatıldığında bu nesnelerin otomatik olarak dispose edilmesini sağlayacak başka bir teknik olmalıdır. 

Bu teknik GC sınıfının Collect() metodunu çağırmak olmadığına göre ve Controls koleksiyonuna eklenmeyen(tabi eklenemeyen nesneler de olabilir) çok sayıda nesne söz konusu ise hepsine tek tek Dispose() metodunu uygulamak mümkündür. Microsoft’un bu konudaki önerisi bütün bu nesneleri(yani Controls koleksiyonuna eklenmeyen..) bir Container’a eklemek ve hepsini birden formun override edilmiş Dispose() metodu içinde dispose etmektir. 

Container’lar hakkında ayrıntılı bilgi vermesem bile Controls koleksiyonuna eklenmeyen nesnelerin nasıl toptan dispose edildiğini örnekleyeceğim. Madem Form1.Designer.cs dosyasında Container tipinde ve components adında bir değişken tanımlanmış yeni bir değişken tanımlamak yerine formun Load olayını temsil eden metotta Container nesnesi hazırlayıp components adı verilen bu değişkene aktaracağım. Bu amaçla yukarıda verdiğim Form1_Load() metodunu aşağıdaki gibi düzenledim. 

private void Form1_Load(object sender, EventArgs e)
 {
    TextBox Text1 = new TextBox();
    Button Dugme1 = new Button();
    components = new Container();
    components.Add(Text1);
    components.Add(Dugme1);
  }

Bu andan itibaren bu 2 nesne components adı verilen Container’ın üyesidir. Eğer bu Container nesnesine Dispose() metodu uygulanırsa bütün üyeleri dispose edilmiş olur ki bu işlem formun override edilmiş Dispose() metodunda yapılmaktadır. Aşağıda Form1.Designer.cs dosyasındaki Dispose() metodunu tekrar verdim.

private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
 {
   if (disposing && (components != null))
    {
      components.Dispose();
    }
  base.Dispose(disposing);
}

Madem bu formun Load olayını temsil eden metodunda Container nesnesi hazırlanıp components adında ve IContainer tipindeki değişkene aktarıldı, artık if (disposing && (components != null)) karşılaştırması doğru değerini verir. Bu karşılaştırma true iken components adlı container nesnesi Dispose() metodu ile dispose edildiğine göre formun Controls koleksiyonuna eklenmeyen nesneler böyle bir yöntemle topluca dispose edilmiş olunuyor. 

Bu şekilde formun Override edilmiş Dispose() metodundaki components adlı değişkenin sırrını çözdükten sonra artık Form sınıfı kaynaklı(aslında IComponent arabirimi kaynaklı) Dispose() metodu üzerinde biraz durabiliriz. Bu amaçla daha önce değişik kez bu kitapta kullanılan bir cümleyi buraya tekrar yazacağım: Show() metodu ile ekrana getirilen formlar herhangi bir şekilde kapatıldıklarında Dispose edilmekte veya bellekten silinmektedir. Tabii form kapatılmadan önce FormClosed ve FormClosing olaylarının meydana geldiğini biliyorsunuz. Bu nedenle formun FormClosed ve FormClosing olayları için aşağıdaki gibi 2 metot hazırlayıp sonra da çalışma anında formu ekrana getirip kapatmak isterseniz önce FormClosing olayıyla ilgili metot işletilir. Devamında FormClosed olayını temsil eden metot işletilir.

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 {
   MessageBox.Show("Form1'le ilgili FormClosing olayı meydana geldi");
 }

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
 {
    MessageBox.Show("Form1'le ilgili FormClosed olayı meydana geldi");
 }

Kapatılmak istenen formla ilgili olarak bu 2 olay meydana geldikten sonra sıra formun Dispose metodunun işletilmesine gelir. Bu 2 olaydan sonra sıranın Dispose() metodunun işletilmesine geldiğini görmek istiyorsanız Form1.Designer.cs dosyasında override edilen Dispose() metodunu aşağıdaki gibi düzenleyebilirsiniz. 

protected override void Dispose(bool disposing)
{
  System.Windows.Forms.MessageBox.Show("Form1'in Dispose metodu işletildi");  
  if (disposing && (components != null))
   {
     components.Dispose();
   }
  base.Dispose(disposing);
}

Sanırım çalışma anında bir form kapatılmak istendiğinde geri planda meydana gelen olayların ve yapılan işlemlerin sıralaması anlaşıldı. Şimdi gelin Form1.Designer.cs dosyasındaki yani Visual Studio tarafından override edilmiş Dispose() metodunu silelim. Tabi üzerinde çalıştığımız proje deneysel amaçlı ve yukarıda sözü edilen “components” adlı IContainer tipindeki nesneye henüz herhangi bir nesne üye yapılmadığı için Visual Studio tarafından hazırlanan override edilmiş Dispose() metodunu silmek bir soruna neden olmaz. Çünkü form kapatılmak istendiğinde Form sınıfının Dispose() metodunun orijinal hali zaten işletilir. Bu tespitleri yaptıktan sonra Form1.cs dosyasında Form1’in Form sınıfı kaynaklı Dispose() metodunu kendim override ettim. Aslında orijinal haline MessageBox sınıfının Show() metodu ile mesaj veren bir satır eklemekle yetindim.

protected override void Dispose(bool disposing)
 {
   MessageBox.Show("Form1'in Dispose metodu işletildi");  
   base.Dispose(disposing);
 }

M
essageBox.Show() satırı hariç bu hali ile Dispose() metodunu override etmenin herhangi bir işlevi yoktur. Çünkü orijinali ile aynıdır. Şimdi bu metottaki base.Dispose(disposing); satırını silip ondan sonra projeyi çalıştırıp formu kapatmayı bir deneyin. Tahmin edeceğiniz gibi bu satır silindikten sonra formu bilinen yöntemlerle kapatmak mümkün olmaz. Çünkü Windows’tan gelen Kapat mesajını engellemiş oldum. Bu şartlarda forma bir düğme yerleştirip Dispose() metodunu aşağıdaki gibi kendiniz işletirseniz formu kapatmış olursunuz. 

private void Kapat_Click(object sender, EventArgs e)
 {
   base.Dispose(true);    
 }

Tabi bu şartlarda formun FormClosing ve FormClosed olaylarını temsil eden metotlar işletilme şansı bulamazlar. Sanırım konu biraz aydınlandı. Tekrar etmek gerekirse; Show() metodu ile ekrana getirilen ve formların Controls koleksiyonlarına eklenen nesneler otomatik olarak Dispose edildikleri için bunları sorun yapmayabiliriz.

C#.NET 30.05.2009 02:51:58

YORUM YOK


YorumlarYorum Yaz
Ana Sayfa | Hakkımda | Kitap Önerileri | Fotoğraflarım | RSS | İletişim
Memik Yanık 2004-2009 © Tüm Hakları Saklıdır.
Hazırlayan www.semgoksu.com