İlkay İlknur

just a developer...

Anonymous Metotlar-Arka Planda Neler Oluyor ?

Merhaba Arkadaşlar,

Her zaman compilerların(derleyicilerin) yazılım geliştirme dünyasındaki en gizemli şeylerden biri olduğunu düşünmüşümdür.Özel olarak C# compilerından bahsedersek;

C# compilerı bir takım tarihsel nedenlerden dolayı C++ kullanılarak yazılmıştır. Yine aynı nedenlerden dolayı şu anda adeta bir kapalı kutu gibi davranmakla birlikte hiçbir şekilde dışarıya açık managed bir API vs.. bulundurmamaktadır. Şu anda C# compilerı kaynak kodları içeren dosyaları almakta ve IL(Intermediate Language) kodlarını üretmektedir. Bununla beraber IL kodlarının üretilmesi sırasında compilerın ne gibi işlemler yaptığı konusunda da bilgi sahibi değiliz. Tabi ki IL kodlarının üretilmesi aşamasında da compiler şüphesiz ki bir takım yeni yapılar üretmektedir.

Anonymous(isimsiz) metotlar bizlerin adı üzerinde de olduğu gibi uygulamamız içerisinde isimsiz metotlar tanımlamamızı sağlamaktadır. Anonymous metotların en yaygın şekilde kullanıldığı yerlerden biri de delegatelerdir.

Örneğin,
btnLambda.Click += (_sender, _args) =>
MessageBox.Show("This is an anonymous function");
};

Basit olarak yukarıdaki kod ile btnLambda isimli butonumuzun Click eventinde çalışacak bir event handler metodu eklemekteyiz. Fakat arka planda neler gerçekleşmekte ? Acaba compiler birtakım ekstra dönüşümler yapmakta mı ?

Öncelikli olarak uygulamamızı Reflector yoluyla açalım

Reflector ile uygulamamızın yapısını incelediğimizde compilerın <Window_Loaded>b__0 isminde bir statik metot yarattığını ve CS$<>9__CachedAnonymousMethodDelegate1 isminde de bir delegate eklediğini görmekteyiz. <Window_Loaded>b__0 metodunun içerisine baktığımızda ise anonymous metot tanımlamasının içeriğini barındırdığını görmekteyiz.

Eğer yukarıda yaptığımız anonymous metot tanımlamasını bir WPF uygulaması içerisinde bulunan Window’un Loaded event handlerı içerisinde gerçekleştirirsek Window_Loaded isimli bu event handlerın reflector ile açılmış IL kodlu halini aşağıdaki gibi görebiliriz.

Window_Loaded içerisinde yapılan işlemleri ise şu şekilde sıralayabiliriz. İlk olarak içerisine yukarıda bahsettiğimiz compiler tarafından üretilmiş static metodu parametre olarak alan bir delegate yaratılmakta daha sonra ise bu yaratılan delegate, Button elementinin Click eventine event handler olarak eklenmektedir.

Anonymous Metotlar İçerisinde Lokal Değişkenlerin Kullanımı

Bence anonymous metotların kullanılmasının en önemli avantajlarından biri de anonymous metotların içerisinde tanımlama yaptığımız kapsam içerisinde bulunan lokal değişkenleri kullanabilmemiz. Çünkü çoğunluklu olarak delegate tanımlayarak yaptığımız event handler tanımlamalarında hiçbir şekilde event handler içerisinde, tanımlama yapılan kapsam içerisindeki lokal değişkenlere erişememekteyiz.

Bu senaryoyu şu şekilde simule edelim

 
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    
int
x = 10;
    
double
y = 198.30;
     btnLambda.Click += (_sender, _args) =>
     {
        
MessageBox.Show(String.Format(
"This is an anonymous function
 result={0}",(x*y)));
     };
}
 

Yukarıdaki metot içerisinde bahsettiğimiz gibi anonymous metot tanımlaması yapıldığı kapsam içerisinde bulunan lokal değişkenler kullanılmakta.

Şimdi uygulamamızın güncellenmiş halini reflector ile tekrardan açarak ve sınıf görünümlerini incelersek aşağıdaki şekildeki gibi bir yapı ile karşılaşabilmekteyiz.

Bu senaryomuzda ise compilerın <>c__DisplayClass1 isminde yeni bir tip yarattığını görmekteyiz. Bu tip içerisinde yukarıda anonymous metot içerisinde eriştiğimiz lokal değişkenleri tutmak üzere kullanılan 2 alanın tanımlandığını ve bir de, bir önceki bölümde bahsettiğimiz gibi anonymous metot içerisinde yapılan işlemleri içerisinde barındıran bir metot  bulunmakta.

Window_Loaded metodunun IL Kodları

Buradaki metot içerisinde ilk olarak yeni bir <>c__DisplayClass1 nesnesi yaratılmakta ve daha sonra ilgili alanlara değer atamaları yapılmaktadır. Son olarak ise compiler yine bir delegate yaratarak bu delegate’e bir önceki adımda yarattığı nesne içerisindeki metodu parametre olarak vermekte ve son olarakta bu delegate'i Button elementinin Click eventine event handler olarak eklemektedir. Eğer anonymous metot içerisinde primitive tipler değilde bir nesne kullanırsakta senaryo yine de yukarıdakine benzer olacaktır. Compiler tarafından yaratılan tip bu sefer kullanılan nesneye erişmek için içerisinde bir nesne referans bulunduracaktır.

Gördüğünüz gibi compilerlar oldukça gizemliler. Programlama dilleri bir takım yeni özellikler sunarken compilerlar bir takım ekstra dönüşümler gerçekleştirmekte ve biz yazılım geliştiricilerin hayatlarını kolaylaştırmaktadır.

Belki de bu yüzden compilerları ve programlama dillerini bu kadar fazla seviyorum. Smile

Bir sonraki yazımızda görüşmek üzere,

Hoşçakalın



Yorum Gönder