C# dilinde “using” anahtar kelimesi iki farklı şekilde kullanılmaktadır. Bunlardan birincisi isim uzaylarını (namespace) koda dahil etmek veya isim uzayları ve türlere başka isimler vermek için kullandığımız using bildirimi, ikincisi ise IDisposable arayüzünü gerçekleştiren nesnelerin doğru bir biçimde ele alınmasını sağlayan using ifadesi. Bu kullanımların her ikisini de örneklerle açıklamaya çalışacağım.
Using Bildirimi (Using Directive)
Using kelimesi sıklıkla isim uzayları (namespace) içerisindeki sınıfların kod içerisinde kolayca kullanılabilmesini sağlamak amacıyla kullanılır. Aşağıdaki kodu inceleyelim:
using System; using System.Linq; using System.Text; using System.Configuration; namespace MyApplication { class Program { static void Main(string[] args) { List<String> list = new List<String>(); list.Add("Seckin Tozlu"); list.Add("Test string 1"); list.Add("Test string 2"); Console.ReadLine(); } } }
Yukarıdaki kodu derlemeye çalıştığımız zaman aşağıdaki hata ile karşılaşırız.
The type or namespace name 'List' could not be found (are you missing a using directive or an assembly reference?)
Hatadan da anladığımız gibi derleyici “List” sınıfını tanıyamıyor. Hatayı gidermek için üst bölümde using bildirimlerinin olduğu kısıma aşağıdaki satırı ekleyebiliriz.
using System.Collections.Generic;
Böylece “System.Collections.Generic” isim uzayını koda dahil etmiş olduk. List sınıfı da bu isim uzayının altında olduğu için derleyici artık bu sınıfı tanıyacaktır. Using bildirimleri, içine yazıldığı dosyanın tamamında geçerli olur. Yani bir .cs dosyasının içerisine bir using bildirimi yazdıysanız, dosyanın her yerinde o isim uzayını kullanabilirsiniz.
Using bildirimlerini kullanmak kolaylık ve okunabilirlik açısından faydalıdır ancak zorunlu değildir. Aşağıdaki koda bakalım:
using System; using System.Linq; using System.Text; using System.Configuration; namespace MyApplication { class Program { static void Main(string[] args) { System.Collections.Generic.List<String> list = new System.Collections.Generic.List<String>(); list.Add("Seckin Tozlu"); list.Add("Test string 1"); list.Add("Test string 2"); Console.ReadLine(); } } }
Gördüğünüz gibi using bildirimini kaldırdık ve List sınıfını, önüne isim uzayının tam adını belirterek oluşturduk. Bu şekilde kullanım mümkündür ancak using kullanmak kodu çok daha kısa ve okunabilir yapacaktır.
Using bildirimi aynı zamanda sınıflara veya isim uzaylarına istediğiniz isimleri vermek için de kullanılabilir. Aşağıdaki kodu incelersek:
using System; using System.Linq; using System.Text; using System.Configuration; using StringListem = System.Collections.Generic.List<string>; namespace MyApplication { class Program { static void Main(string[] args) { StringListem list = new StringListem(); list.Add("Seckin Tozlu"); list.Add("Test string 1"); list.Add("Test string 2"); Console.ReadLine(); } } }
En sonuncu using bildirimine bakacak olursak System.Collection.Generic
isim uzayındaki List
türüne “StringListem” diye bir isim veriyoruz ve bu ismi kod içerisinde kullanıyoruz. Bu şekilde sınıflara veya isim uzaylarına başka isimler vererek kod içerisinde kullanmamız mümkündür. Şimdi using ifadesinin nasıl kullanıldığına bakabiliriz.
Using İfadesi (Using Statement)
Using ifadesinin nasıl kullanıldığına bakmadan önce .NET çatısında yer alan “managed resource” ve “unmanaged resource” kavramlarını bilmekte fayda var. Bunların Türkçe karşılığı ne olmalı bilemiyorum ama bulabildiğim en mantıklı çeviri “yönetimli kaynak” ve “yönetimsiz kaynak” oldu. .NET içerisinde Java’da olduğu gibi garbage collector (çöp toplayıcı) mekanizması vardır. Bellekteki bir nesne artık hiçbir referans tarafından gösterilmiyorsa o nesne artık kullanılmıyor demektir ve çöp toplayıcı bunu gördüğü zaman o nesneyi bellekten siler. Yönetimli ve yönetimsiz kaynak kavramı işte tam burada anlam kazanıyor. Çöp toplayıcının tespit edip gerektiği zaman bellekten silebildiği öğeler yönetimli kaynaklar (managed resource) olarak adlandırılır. Çöp toplayıcı bu öğeler üzerinde tam kontrole sahiptir. Ancak çöp toplayıcının kontrolünde olmayan kaynaklar da vardır ve çöp toplayıcı bu kaynakarı hiç kullanılmıyor olsalar bile serbest bırakamaz. Dolayısıyla bu kaynakların yazılımcı tarafından serbest bırakılması gerekir. Bu kaynaklara yönetimsiz kaynak (unmanaged resource) adı verilir. Bunlara örnek olarak veritabanı bağlantılarını, soketleri veya dosyaları verebiliriz.
Yönetimsiz kaynakların yazılımcı tarafından serbest bırakılması gerektiğini söyledik. Yönetimsiz kaynaklara erişen bütün sınıflar IDisposable arayüzünü uygularlar ve bu arayüz içerisindeki Dispose() metodunu override ederler. Yazılımcı olarak bizim görevimiz de bu nesnenin Dispose metodunun her koşulda çağırılmasını sağlamaktır. Peki bunu nasıl başarabiliriz? Aşağıdaki koda bakalım:
{ Font font1 = new Font("Arial", 10.0f); try { byte charset = font1.GdiCharSet; } finally { if (font1 != null) ((IDisposable)font1).Dispose(); } }
Font sınıfı yönetimsiz kaynaklara erişen bir türdür. Dolayısıyla işimiz bittikten sonra bu nesne üzerinde Dispose metodunu çağırıp kullandığımız kaynakları serbest bırakmalıyız. Bunu yapmak için finally bloğu içerisinde font1 referansı üzerinden Dispose metodunu çağırıyoruz. Finally bloğu her koşulda çalışacağını kesin olarak bildiğimiz kod satırlarını barındırır. Yani try bloğu içerisinde bir exception fırlasa bile finally bloğu içerisindeki Dispose metodu çağrılacak ve kaynaklar serbest bırakılacaktır. Böylece yazılımcı olarak sorumluluğumuzu yerine getirmiş oluyoruz. Using ifadesi de aynen bu amaçla kullanılmaktadır. Şimdi aşağıdaki koda bakalım:
using (Font font1 = new Font("Arial", 10.0f)) { byte charset = font1.GdiCharSet; }
Burada font1 nesnesini using ifadesi içerisinde yaratıyoruz ve using bloğu içerisinde kullanıyoruz. Bu kod derlendiği zaman yukarıda verdiğim try-finally bloklarını içeren koda dönüştürülmektedir. Yani bu iki kod aynı şeyi yapmaktadır. Using ifadesi içerisinde IDisposable arayüzünü uygulayan sınıflardan nesneler yaratıp kullanabiliriz. Using bloğu bu nesnelerin kullandığı yönetimsiz kaynakları doğru bir biçimde serbest bırakacaktır. Böylece blok içerisinde hata oluşsa bile using kullandığımız için Dispose metodu çağrılacak ve yönetimsiz kaynaklar serbest bırakılacaktır. Using kullanarak yönetimsiz kaynakların doğru bir biçimde serbest bırakılmasını garanti etmiş oluyoruz. Using ifadesi içerisinde aşağıdaki gibi birden çok nesne tanımlamamız da mümkündür.
using (Font font3 = new Font("Arial", 10.0f), font4 = new Font("Arial", 10.0f)) { // font3 and font4 uzerınde islemler yap }
Using ifadesi sadece yönetimsiz kaynaklara erişen nesneler için kullanılmak zorunda değildir. Teorik olarak using içerisinde IDisposable arayüzünü uygulayan her nesneyi kullanabiliriz. IDisposable arayüzünü uygulayan nesneler ise yönetimsiz kaynaklara erişiyor olabilirler veya kullanıldıktan hemen sonra serbest bırakılmaları gerekiyor olabilir. Başka bir deyişle IDisposable arayüzünü uygulayan her nesne yönetimsiz kaynakları kullanmak zorunda değildir. Bazı nesnelerin (örneğın çok büyük boyutlu bir resim) çöp toplayıcının müdahalesini beklemeden bellekten silinmesi gerekiyor olabilir. Bu nesneler de using ifadesi içerisinde kullanılarak kullanımdan hemen sonra serbest bırakılmaları sağlanabilir. Using bloğu kullanmadan yaratılan nesneler yönetimsiz kaynakları serbest bırakmayacağı için bellek sızıntıları ve kötü performansa neden olabilirler.
teşekkürler faydalı bir yazı oldu
Bu using-in ne oldugunu dunden beri ariyorum. sonunda buldum . tesekkurler gercekten 🙂
teşekkürler
Anlaşılır ve istifade edilebilir bir üslubunuz var. Binler teşekkür…
Çok güzel vede faydalı bir makale. Başarılarınızın devamını dilerim.
Gerçekten benim için çok faydalı ve anlaşılır bir yazı oldu. Emeğiniz ve paylaşımınız için sonsuz teşekkürler.
Parmaklarına sağlık güzel bir sunuş detaylı bir anlatım olmuş. Başarılar…
“çöp toplayıcı bu kaynakları hiç kullanılmıyor olsalar bile serbest bırakamaz.” (unmanaged)
Bu cümle doğru bir cümle değil. .net de yönetimsiz kaynaklar yönetimli bir kaynağa (sınıfa) bağlı olarak üretilir ve yönetimli kaynak çöp toplayıcı tarafından bellekten kaldırılırken IDisposable arayüzü ile Dispose metodu zaten otomatik çağırılır. Siz manuel Dispose metodunu çağırırsanız yönetimsiz kaynakları erken bellekten kaldırırsınız. using ile siz bu işlemi çöp toplayıcıya değil kendiniz daha erken bir şekilde yapmış olursunuz. Avantajı hafızayı daha erken boşaltmaya yarar. Yoksa çöp toplayıcı yönetimsiz kaynağı boşaltamaz diye bir durum yok, böyle olsaydı .net de hafıza sızmalarından (memory leak) geçilmezdi.
çok teşekkürler gerçekten bilgilendirici olmuş. Devamını dilerim
Elinize sağlık gayet açıklayıcı olmuş.
cok gozel anlatim, elinize saglik
Hocam eline koluna sağlık 10 numara anlatmışsın.