object ve dynamic

Son zamanlar sıkça "dynamic" ve eski dostumuz "object" arasında ne fark olduğu sorusuyla karşılaşıyorum. İkisi arasında bir fark var mı? Bu sorunun yanıtı hem evet hem hayır aslında. Eğer, arka planda yapılan işleri bilmiyorsanız, evet, rahatlıkla object kullandığınız her yerde kullanabilirsiniz ve derleme-zamannda herhangi bir hata ile karşılaşmazsınız. Sanırım yazımın devamını okuyarak kararı sizin vermeniz en doğrusu.

Önceliği eski dostumuz "object"’te verirsem sanırım kimse alınmaz 🙂 object, hepinizinde bildiğini biliyorum ama, "System.Object"’e kısayoldan başka bir şey değil aslında ve C#’ın ilk sürümünden beri hayatımızda. C#’ta neredeyse herşeyin bir nesne olduğu ve object’den türediğini düşünürsek ne kadar güçlü olduğunu anlayabiliriz; neredeyse her değeri atayabiliriz.

Yazımın geri kalanında karşılaştırmayı örnek bir kod üzerinden yapmak daha iyi olacak sanırım. Aşağıda basit bir kod parçacığı göreceksiniz;

object nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

bu kod parçacığının çıktısını sorsam, eminim ki "Tüm makale hatalıymış :P" diyenleriniz olacaktır, ne de olsa "nesne int değil bir object olarak tanımlanmış"; ama gerçekte çıktı "Tabi ki türü int". Her ne kadar nesne tanımlaması sırasında object olarak belirlenmişte olsa çalışma-zamanında içerisine konulan değer bir int.

Bu örnekte nesne içerisinde her ne kadar bir int türünden veri yer alsa da, üzerinde bir int’e uygulayabileceğiniz toplama işlemi gibi basit bir işlemi yapmaya çalıştığınızda bakın neler oluyor;

object nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

nesne = nesne + 1;

İlk örneğimiz sorunsuz olarak derlenirken, bu basit değişiklik sonrasında kodumuz derleme sırasında hata alacaktır ve derlemek isteğimizde öncelikle nesne’yi int türüne dönüştürmeliyiz;

object nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

nesne = (int)nesne + 1;

Bu basit dönüşüm, derleyiciye ne yaptığımızı bildiğimizi belirtmenin bir yolu: nesne’m bir int ifadedir. Bu noktada derleyici için nesne’nin değeri bir object olmaktan çıkar. Tabi ki, önemle not düşmem gerekir ki, tür dönüşümünü yaparak derleme-zamanı hata alınmaması her şeyin %100 doğru olduğu anlamına gelmeyecektir. Bu duruma örnek vermek gerekirse, aşağıdaki kod parçacığında nesneyi string türüne harici olarak dönüştürme işlemi derleme-zamanında bir hataya neden olmayacak; fakat derlenen kod çalıştırıldığında çalışma-zamanı hata alınacaktır:

object nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

nesne = (string)nesne + 1;

Derleyici, siz harici olarak belirtmediğiniz sürece, nesne’yi object türünden kabul etmekte ve üzerinden başka bir türe ait işlem yapmaya izin vermemekte; fakat kazayla içindeki değerden yukarıdaki örnekte olduğu gibi harici olarak farklı bir tür’e dönüştürülmesi çalışma-zamanı hataya neden olacaktır.

.Net 4.0’la sahne alan önemli yeniliklerden biri olan “dynamic”, kabaca anlatmak gerekirse, harici olarak derleyiciye bu tür üzerinde derleme sırasında herhangi bir kontrol yapılmayacağını belirtir. Yapılacak olan işlemler çalışma-zamanındaki veriler doğrultusunda yorumlanarak yerine getirilir. İlk örneğin dynamic versiyonu da aşağıdaki örnekte de göreceğiniz gibi ilk kullanıma oldukça benzer:

dynamic nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

Üstelik, ilk object örneğinden farklı olarak, aşağıdaki kod herhangi bir tür değişimine ihtiyaç duymaksızın hatasız şekilde derlenir;

dynamic nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
 }  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

nesne = nesne + 1;

Bunun sebebi, dynamic’i tanıtırken de belirttiğim gibi, derleme-zamanında tür üzerinden kontrol yapılmaması. İşte bu object ile dynamic arasındaki en önemli farktır. Nesnenin dynamic ile tanımlanmasıyla birlikte programcı derleyiciye bu nesne içindeki veri türünün ancak çalışma-zamanında belli olabileceğini ve bu sebeple de derleme zamanında hata vermemesi gerektiğini belirtir. Sonuç olarak da, derleyici bu veri türü için yapılan işlemlere müdahale etmez. Aşağıdaki kod parçacığının son satırı bahsettiğim duruma basit bir örnek olacaktır:

dynamic nesne = 1;

if (nesne.GetType() == typeof(int)){
     Console.WriteLine("Tabi ki türü int");
}  else {
     Console.WriteLine("Tüm makale hatalıymış :P");
}

nesne.VarolmayanBirMethod();

     Bu kod parçacığı sizinde göreceğiniz gibi hatasız derlenecek; fakat çalışma zamanında nesne içerisinde VarolmayanBirMethod bulunamadığı için çalışma-zamanı hatası alınacaktır.

 

Peki derleyici dynamic türler üzerinde derleme sırasında kontrol yapmıyorsa nasıl bir işlem yapıyor?

      dynamic tanımlanan türler üzerinde yapılan işlemler (örneğin method çağrıları) hakkında derleme zamanında analiz yapılarak çağrılan metodun ismi, parametre sayısı, parametre türleri, bağlayıcı türü(c# nesnesi, python nesnesi, COM nesnesi) v.b. bilgiler çalışma-zamanında kullanılmak üzere saklanır ve çalışma-zamanında tür’ün aldığı değer doğrultusunda bu bilgiler kullanılarak talep edilen işlemler gerçekleştirilir. Dolayısıla eksik ve/veya hatalı bilgi verilmesi (olmayan bir metod adı, eksik parametre) derleme-zamanı değil çalışma-zamanı hataya neden olacaktır.

     Yapılan bu çalışma-zamanı yorumlama işi tabi ki uygulamanıza ek bir yük getirecektir (işlemci zamanı ve hafıza kullanımı olarak), bu ek yükün hafifletilmesi anlamında gerekli önbellek işlemlerinin yapıldığını da not olarak düşmem gerekir. Bu sayede, örneğin bir döngü içerisinde yapılan bir dynamic çağrıda ilk defadan sonra yeniden bir yorumlama yapılmayarak önbellekte hazır bulunan kod parçacığı işletilir.

    dynamic hakkında unutulmaması gereken önemli bir noktada, arka planda kullanılan Dinamik dil çalışma zamanı kütüphanesinin (Dynamic Language Runtime – DLR) .Net için sadece C# diliyle yazılmış bir kütüphane olduğudur, aynı sizlerin yazdığı  kütüphaneler gibi. Dolayısıyla da yukarıdaki örneklerdeki gibi kullanımlarda hızlı, okunur kod yazılmasını sağlamakla birlikte normalde yapılabilecek basit bir tür dönüşümünden öteye geçilerek arka planda sizin yerinize yapılan çağrılar nedeniyle kodun performansı düşecektir.

"BÜYÜK BİR GÜÇLE BİRLİKTE BÜYÜK SORUMLULUKTA GELMELİDİR"

C# 4.0 ile birlikte gelen önemli özelliklerde birisi olan “dynamic” temelde iki amaca hizmet vermesi için getirilmiştir;

  • C# ve COM birlikte işlerliğinin kolaylaştırılması
  • C#  ve dinamik dillerin (Javascript, Python, Ruby v.b.) birlikte işlerliğinin sağlanması  ve kolaylaştırılması

  Bu amaçlar dışında kullanılalabiliyor olmasına karşın; başta performans olmak üzere, derleme zamanı hataların farkedilememesi v.b. nedenlerle tavsiye edilmemektedir, sadece gerekli olduğunda ve çok dikkatli biçimde kullanılmalıdır.

Fatih Boy

Ankara'da yaşayan Fatih, bir kamu kurumunda danışman olarak çalışmaktadır. ALM süreçleri, kurumsal veri yolu sistemleri, kurumsal altyapı ve yazılım geliştirme konularında destek vermektedir. Boş zamanlarında açık kaynak kodlu projeler geliştirmeyi ve bilgisini yazdığı makalelerle paylaşmayı seven Fatih, aynı zamanda Visual C# ve Visual Studio teknolojileri konusundan Microsoft tarafından altı yıl üst üste MVP (En Değerli Profesyonel) ödülüne layık görülmüştür. İş hayatı boyunca masaüstü uygulamaları, web teknolojileri, akıllı istemciler gibi konularda Asp.Net, Php, C#, Java programlama dilleri ve MySql, MsSql ve Oracle gibi veritabanı yönetim yazılımları ile çalışmıştır. İngilizce ve Türkçe olarak yayınlanan makalelerini gerek İngilizce bloğunda, gerekse de Türkçe bloğunda bulabileceğiniz gibi web sitesinden de açık kaynak kodlu geliştirdiği yazılımlarına ulaşabilirsiniz. vCard - Twitter - Facebook - Google+

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir