İlkay İlknur

just a developer...

.NET Framework 4.0 Beta 2 - Lazy Sınıfı Kullanılarak Lazy Initialization Sağlanması

Merhaba Arkadaşlar,

Yazılım geliştirme süreci içerisinde en sık yaptığımız işlemlerden biri nesne yaratma işidir. Bir uygulama içerisinde belki yüzlerce belki de binlerce kez nesne yaratırız ve bu nesneleri kullanırız. Yarattığımız nesnelerin bazıları sadece basit üyeler içeren nesneler olurken bazıları ise içerilerinde complex üyeleri barındabilen nesneler olabilmekte. Bazı nesneler ise içerlerinde sadece bir üye barındırsalarda bu üye oldukça fazla memory harcayabilir. Bu nedenlerden dolayı aslında çoğu zaman düşünmeden yaptığımız nesne yaratma işlemlerinde çok daha dikkatli olmamız gerekir. Yani bellekte fazla yer kaplayacak bir nesneyi en baştan yaratmak yerine o nesneye ihtiyacımız olacağı yerde yaratmak uygulamamızı çok daha etkin bir hale getirecektir. Yazılım dünyasında bu kavrama Lazy Initialization denmektedir. Çoğu zaman bu ihtiyacımızı karşılamak için çeşitli patternlara bağlı kalarak bahsettiğimiz fonksiyonaliteyi sağlayabilmekteydik. Ancak .NET Framework 4.0 ile birlikte Lazy<T> sarmalayıcı sınıfı kullanarak kolay bir şekilde Lazy Initialization sağlayabilmekteyiz. Şimdi gelin hep beraber Lazy<T> sınıfının üyelerine öncelikle bir göz atalım.

Lazy<T> Sınıfı

Lazy sarmalayıcı sınıfı System namespace'i içerisinde yer almaktadır. Lazy sınıfının constructorlarına baktığımızda 4 farklı constructor karşımıza çıkmakta. Func<T> tipindeki delege Lazy sınıfı içerisinde sarmalanan sınıfının yaratılacağı sırada çalışacak olan metodu gösterecektir. Boolean tipteki bool parametresi ise Lazy sınıfının ThreadSafe olup olmayacağını göstermektedir. Yazımızın ilerleyen bölümlerinde bu kavrama da değiniyor olacağız. Lazy sınıfının üyelerinde baktığımızda ise IsValueCreated isimli üye sarmalanan sınıfın yaratılıp yaratılmadığını belirten bir boolean değerdir. Value üyesi ise sarmalanan sınıfı göstermektedir. Sınıfın üyelerine bu üyeyi kullanarak erişiyor olacağız. Öncelikle basit olarak bir sınıf oluşturalım ve daha sonra Lazy Initialization mekanizmasının nasıl Lazy<T> sınıfı tarafından sağlandığını görmeye çalışalım. Öncelikle basit bit Insan sınıfı yaratıyoruz. class Insan {    public int ID { get; set; }    public string Ad { get; set; }    public string Soyad { get; set; }  
   public Insan()
   {
       ID = 1;
       Ad = "İlkay";
       Soyad = "İlknur";
   }
}   Şimdi Lazy sınıfımızı yaratıyoruz ve Insan sınıfının ne zaman yaratıldığını inceliyoruz.
static void Main(string[] args)
{
   Lazy<Insan> insan = new Lazy<Insan>();
   Console.WriteLine("Yaratıldı mı : "+insan.IsValueCreated);
   Console.WriteLine("ID : {0}\nAd: {1}\nSoyad: {2}",insan.Value.ID,insan.Value.Ad,insan.Value.Soyad);
   Console.WriteLine("Yaratıldı mı : " + insan.IsValueCreated);
   Console.ReadLine();
}
Uygulamamızı çalıştırırsak. Gördüğümüz üzere nesnemiz lazy nesnesi oluşturulma sırasında yaratılmadı. Biz ne zaman nesnenin bir üyesine erişmek istedik o zaman nesne yaratıldı ve kullanıldı. Yukarıdaki örneğimizde Insan sınıfının bir constructorı vardı ve o constructorda atanan değerlerle biz nesnemizi kullanıyorduk. Şimdi ise Lazy sınıfının bir diğer kullanım şeklini inceleyeceğiz. Bu senaryomuzda ise öncelikle Insan sınıfı içerisinde bulunan constructorı siliyoruz ve Lazy sınıfını tanımladığımız yere (Örnekte Console uygulamasının çalıştığı Program sınıfı) bir GetInsan isimli bize bir Insan nesnesi döndüren aşağıdaki metodu yazıyoruz. static Insan GetInsan() {    return new Insan()    {        ID=2,        Ad="Çağdaş",        Soyad="Olgun"
   }; }
Daha sonra Lazy sınıfının yaratılmasını da şu şekilde değiştiriyoruz.
Lazy<Insan> insan = new Lazy<Insan>(() => GetInsan());
Şimdi ise uygulamamızı çalıştıralım ve sonuçları gözlemleyelim. Gördüğümüz gibi Insan sınıfı yine sadece belirli bir üyesine ihtiyaç duyulunca yaratıldı. Yaratılma şeklini ise bu sefer farklı bir şekilde gerçekleştirdik. Yaratılma sırasında Lazy sınıfı parametre olarak aldığı lambda ifadesindeki kodu çalıştırdı ve buradaki sonucu doğrudan sarmaladığı tipe yansıttı. Ayrıca GetInsan metodu içerisindeki ifadeleri doğrudan  bu lambdanın gövdesine koyabilirdik. Bu şekilde de yine aynı fonksiyonaliteyi sağlayabiliriz.Wink

Multithread Yapılarda Lazy<T> Sınıfının Kontrolü

Lazy<T> sınıfını kullanırken aklımıza gelecek durumlardan biri de Multithread durumlar. Birden çok threadin aynı lazy nesnesine erişmesi sonucunda Lazy sınıfının sarmaladığı nesneyi sadece bir kere yaratmasının garanti altına alınması gerekmektedir. ThreadSafe adı verilen bu özellik bizim kullandığımız Lazy sınıfı içerisinde zaten implemente edilmiş durumda ve varsayılan olarak true değeri atanmış durumda. Böylece multithread uygulamalarda da lazy sınıfının sarmaladığı sınıf sadece bir kez örneklenmektedir. Lazy<T> sınıfının constructo rlarına baktığımızda bu özelliği opsiyonel olarak false değerine çekebildiğimizi görmüştük. Bunun nedeni ise tek  thread üzerinde çalışılacağının garanti olduğu durumlarda bu threadsafe mekanizmasının devre dışı bırakılmasıyla bir performans kazanımının elde edilebilmesidir. Gördüğümüz üzere Lazy sınıfı özellikle yüksek miktarda bellek kaplayacak olan sınıfların örneklenmesinde oldukça etkin bir mekanizma sağlamaktadır. Örneğin içerisinde Picture, Stream gibi sınıfları barındıran sınıfların örneklendirilmesinde Lazy sınıfının kullanılmasının oldukça yararlı olduğunu düşünüyorum. Görüşmek Üzere,  


Yorum Gönder