Makale Özeti

C# 4.0 ile gelen yenilikler arasında dinamik anahtar kullanımı oldukça işimize yarayacağa benziyor. Framework 4.0 öncesinde bir metod ya da expression’dan dönen tipi bilme gibi bir zorunluluğumuz vardı. Dinamik anahtar kelimesi sayesinde çalışma zamanında oluşturulan nesnelerin ya da assign edilen expressionların tipini belirtmemize gerek kalmadan sistem çalışma zamanında kendini doğru tipe bind eder.

Makale

Dynamic Anahtar Kullanımı

C# 4.0 ile gelen yenilikler arasında dinamik anahtar kullanımı oldukça işimize yarayacağa benziyor. Framework 4.0 öncesinde bir metod ya da expression’dan dönen tipi bilme gibi bir zorunluluğumuz vardı. Dinamik anahtar kelimesi sayesinde çalışma zamanında oluşturulan nesnelerin ya da assign edilen expressionların tipini belirtmemize gerek kalmadan sistem çalışma zamanında kendini doğru tipe bind eder. Aşağıda bulunan örnekle ne demek istediğimi eminim daha iyi anlayacaksınız.

Object , Var ve Dynamic arasındaki temel farklılıklar:

Object:

"object variable1" demek System.Object variable1 'in kısayoludur. Object tipinde tanımlanan bir değişkenin System.Object tipinde olduğu ve strongly type olduğunu belirtir. Değişken object tipinde tanımlandığı için her türlü atamayı yapabilirsiniz. Fakat object tipinde bir değişkeni kullanabilmek için kendi tipine çevirmemiz gerekmektedir.Aşağıdaki gibi bir kullanımda hata alırsınız.

object variable1 = 3;

object variable2 = 5;

object result = variable1 + variable2;

HATA! variable1 ve variable2 değişkenlerini, tipleri olan int'e çevirmeden böyle bir işlemde kullanamazsınız.

variable1 = "Erkan";

variable2 = "Dervis";

BAŞARILI! daha önce int tipinde yapılan atama olmasına rağmen devam eden satırlarda variable1 ve variable2 değişkenlerine string bir değer atayabiliriz ve string'e cast yaptığımızda içindeki değeri sorunsuz olarak alabiliriz. Gördüğünüz gibi Object kullanıldığı zaman her türlü atamayı yapabilirsiniz yeter ki onu kendi tipine(doğru tipe) cast edip kullanın.

Var:

variable1 değişkeninin kendisine atanan değer tipinde ve strongly typed olduğunu belirtir.variable1 değişkenine atama yapmak istediğimizde sadece kendisine atanan ilk değişken tipinde atamalara izin verir. Demek istediğim variable1 = 3 değerini atayarak int türünde bir değişken olduğunu belirttik ve artık string tipinde bir atama yapamayız.

var variable1 = 3;

var variable2 = 5;

var result = variable1 + variable2;

BAŞARILI! herhangi bir cast yapmamıza gerek kalmadan sonuç 8 olur.

variable1 = "Erkan";

variable2 = "Dervis";

HATA! Daha önce variable1 ve variable2 değişkenlerine int tipinde bir değer atadığımız için string tipinde bir değere izin vermeyecektir.

Dynamic:

"dynamic variable1" dinamik olarak atanan bir değişkenin en önemli avantajı hangi tipte değer set ederseniz run-time anında o tipe dönüşerek onun özelliklerini alabilmektedir.

dynamic variable1 = 3;

dynamic variable2 = 5;

dynamic result = variable1 + variable2;

BAŞARILI! Ne demiştik dynamic kendisine atanan değerin tipine run-time anında dönüşür ve o tipin özelliklerini kazanır.

variable1 = "Erkan";

variable2 = "Dervis";

BAŞARILI! Daha önce int tipinde değer atılmasına rağmen en son atılan değerin tipi neyse o tipin özelliklerini kazanır. Bir diğer özelliği ise dynamic tipi compiler'in derleme zamanında tip tahmini yapmaz bunu run-time 'da yapar.

Örnek 1:

dynamic dNumber = 7;

dynamic dString = "Hello world";

dynamic dDate = System.DateTime.Today;

Yukarıda örnekte görmüş olduğunuz üzere dynamic anahtarını istediğimiz değişken için kullanabilmekteyiz. Ama asıl işimizi görecek bölüm şimdi başlıyor..

Örnek 2:

Dynamic öncesi reflection:

object calculate = GetCalculation();

Type rtype = calculate.getType();

object cObj = rtype.InvokeMember("Multiply", BindingFlags.InvokeMethod, null, new object[] { 3,5 });

int result = Convert.ToInt32(cObj);

GetCalculation metodu bize Calculation adlı class'ın yeni bir instance'ını oluştursun. Calculation class'ında bulunan Multiply metodunun ise 2 parametre aldığı ve aldığı parametreleri çarptığını ve bize int tipinde değer döndürdüğünü farzedelim. Bu örnekte Calculator sınıfının tipini bilmediğimizi farzedelim ve normal reflection uygulayarak ilgili metodu invoke edelim.

Dynamic ile reflection:

dynamic calculate = GetCalculation();

int result = calculate.Multiply(3,5);

Öncesinde reflection ile yaptığımız ve methodun ismini parametre olarak geçip invoke ettiğimiz işleri dynamic anahtar kelimesi ile çok daha basit bir şekilde gerçekleştirebilmekteyiz.

Gördüğünüz üzere dynamic anahtar kelimesini kullanarak Calculation sınıfının bütün özelliklerini calculate objesine yükledik. Herhangi bir reflection uygulamamıza gerek kalmadan direk olarak ilgili class'ın Multiply metodunu çağırabildik.

Örnek 3:

class Urun

{

    public void UrunOlustur()

    {

        Console.WriteLine("Ürün Olusturuldu.");

    }

}

 

class Musteri

{

    public void MusteriOlustur()

    {

        Console.WriteLine("Müsteri Olusturuldu.");

    }

}

public enum IsListesi { Urun, Musteri };

 

public static object Olustur(IsListesi isListesi)

{

    switch (isListesi)

    {

        case IsListesi.Musteri:

            return new Musteri();

        case IsListesi.Urun:

            return new Urun();

        default: return null;

    }

}

 

static void Main(string[] args)

{

    dynamic dynamicObject = Olustur(IsListesi.Musteri);

    dynamicObject.MusteriOlustur();

    Console.Read();

}

 

Bu örnekte ise Musteri sınıfında bulunan MusteriOlustur() metodunu, dinamik anahtar kelimesini kullanarak herhangi bir casting ya da reflection kullanmadan çağırabildik.

Named ve Optional Parametreler

Optional Parameters:

Metodumuzun prototipini yazarken opsiyonel parametre kullanmamıza olanak sağlar. Metodumuzu çağırdığımız zaman prototipte yazılı olan bütün parametreleri göndermek yerine arzu ettiğimiz kadarını gönderip geri kalanların default değer almasını sağlayabiliriz.

Örnek :

public void Musteri(string adi,string soyadi,string uyrugu="T.C.")

{

    Console.WriteLine("Adi:" + adi);

    Console.WriteLine("Soyadi:" + soyadi);

    Console.WriteLine("Uyrugu:" + uyrugu);

}

static void Main(string[] args)

{

    Musteri("Erkan","Dervis");

}

Müşteri metodumuzun prototipinde 3 parametre bulunmasına rağmen biz metodu çagırırken 2 parametre gönderdik ve diğer parametre default olarak tanımlanan değeri otomatik olarak aldı. Ekranın çıktısı asağidaki gibidir.

Adi: Erkan

Soyadi:Dervis

Uyrugu: T.C.

En büyük avantajlarından biri bazı durumlarda gereksiz yere method overloading yapmamıza gerek kalmayacak olmasıdır. Basit bir örnek ile gösterecek olursak;

Örnek:

Optional Parameters öncesi:

public void CalculatePrice(decimal price,bool includeTax)

{

  

}

 

public void CalculatePrice(decimal price)

{

    CalculatePrice(price, false);

}

CalculatePrice adlı metodumuzun kendisine parametre olarak gönderilen price(fiyat) ile (includeTax) kdv 'nin dahil olup olmadığına bakarak ücreti hesapladığını düşünelim.

Optional Parameters ile:

public void CalculatePrice(decimal price,bool includeTax=false)

{

  

}

 

Yukarıda 2 ayrı metodla yaptığımız işlemi optional Parameters ile bir metoda nasıl düşürebildiğimizi gördük.Method overloading yapmamıza gerek kalmadı.

 

Named Parameters:

Metodu çağırırken parametreleri, metodun prototipinde yazan sırayla değil de istediğimiz sıraya göre parametre isimlerini belirterek göndermemizi sağlar.

Örnek :

public void Musteri(string adi,string soyadi,string uyrugu="T.C.")

{

    Console.WriteLine("Adi:" + adi);

    Console.WriteLine("Soyadi:" + soyadi);

    Console.WriteLine("Uyrugu:" + uyrugu);

}

static void Main(string[] args)

{

    Musteri(soyadi:"Dervis",adi:"Erkan");

}

Yukarıda bulunan örnekte görmüş olduğunuz üzere metodun parametre sırasını, parametre ismini tanımlayarak istediğimiz şekilde gönderebiliyoruz ve run time anında doğru parametreye değer set edilebiliyor. Yani metodun prototipinde yazılı olan parametre ismini yazip ":" koyarak sağ tarafına da değişkeni göndermemiz yeterli olacaktır. Ekran çıktısı optional parameters'da olduğu gibidir.

Com Arayüzleri:

Named ve Optional parametrelerin gelişiyle beraber Com Api lerini çağrırken ve kullanırken sağladıkları büyük avantajlarda bulunmaktadır.

C# 3.0 ve öncesinde word dokümanı açabilmek için aşağıdaki kod bloğunda görmüş olduğumuz üzere 16 parametrelik Open metodunu çağırırken bütün parametreleri object tipinde ve ref olarak girme zorunluluğu vardı.

Optional Parameters ile Ommit Ref Özelliği:

 

Framework 4.0 Öncesi:

 

Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

wordApp.Visible = true;

object fileNamePath = "C:\\Grades.docx";

object missingValue = Missing.Value;

wordApp.Documents.Open(ref fileNamePath,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue);

Framework 4.0 ile:

Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

wordApp.Visible = true;

wordApp.Documents.Open("C:\\Grades.docx");

 

Optional parameters sayesinde metodun parametreleri daha anlaşılır hale gelmiş ve kısalmıştır. Farkındaysanız word dokümanının yolunu object tipinde değil direk ismi ile gönderdik ve ref i parametreleri gönderirken gözardı ettik (ommiting ref while passing parameters).

 

Named Parameters ile Ommit Ref Özelliği:

Framework 4.0 Öncesi:

Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

wordApp.Visible = true;

object fileNamePath = "C:\\Grades.docx";

object missingValue = Missing.Value;

object documentVisible = false;

wordApp.Documents.Open(ref fileNamePath,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref missingValue,ref documentVisible,ref missingValue,ref missingValue,ref missingValue,ref missingValue);

Framework 4.0 ile:

Word.Application wordApp = new Microsoft.Office.Interop.Word.Application();

wordApp.Visible = true;

wordApp.Documents.Open(Filename:"C:\\Grades.docx",Visible:false);

 

Named parameters ile metodun prototipinde bulunan parametrelerin sıralarına uymamıza gerek kalmadan sadece kullanmak istediğimiz parametreleri "parametreismi:değer" şeklinde gönderebiliyoruz. Optional parameters ta olduğu gibi burada da ref i parametreleri gönderirken gözardı ettik (ommiting ref while passing parameters).

 

Bir başka makalede tekrar görüşmek dileğiyle..

 

Erkan DERVİŞ

Bilgisayar Mühendisi

 

Kaynaklar:

MSDN

Techui

http://msdn.microsoft.com/en-us/library/dd264739(VS.100).aspx

http://weblogs.asp.net/podwysocki/archive/2008/10/29/c-4-0-named-and-optional-parameters-behind-the-scenes.aspx