in Eski Blog Yazılarım

C# da ki Action.Action(void () target)

Her geçegün .Net Framework bataklığında daha da derinlere batıyoruz :) İhtiyaçlar gün geçtikce değişiyor ve buna bağlı olarak developer’ında program yazma şekli, ihtyaçları
değişiklik gösteriyor en son developer ihtiyaçlarına göre de .Net Framework değişiyor, gelişiyor. İşle bu arz-talep zincirinden çıkmış güzel bir tip daha Action Delegate.

Action .NET 3.0 ile birlikte developer’ın hayatına girmiş çok kullanışlı ve güclü bir delegate’tir. Genelde void tipindeki method’larla kullanılır ve geri dönüş değerini geriye döndürmez.

Ben genelde Collection nesnelerinde ForEach() methodunda kullanıyordum ama aşağıdaki gibi seksi yerlerde’de kullanma fırsatı buldum.

Not: Action’ın benzeri ve geriye değer döndüren delegate arıyorsanız Func Delegate’ine bakabilirsiniz => http://msdn.microsoft.com/en-us/library/bb534960.aspx

Action’ın ne olduğu zaten bir çok sitede yazıyor. Benim aktarmak istediğim nokta ise kullanım çeşitleri.

Hemen kod’a zıplayalım :

Örneğin bir hesap makinesı yapmaya kalkalım ve tasarlarkende Action delegate’ini kullanalım.
Bir hesap makinasında bir çok fonksiyon vardır.
Kimi fonksiyonlar tek parametre alır, kimisi çift, kimisi belirsiz sayıda parametre alır yani Signature’ları farklıdır. Action burda yardımımıza koşuyor ve burdaki kod yönetim sıkıntısını aşmamızı sağlıyor.

class Islemler
{
public void Topla(int X, int Y)
{
Console.WriteLine("Toplama İşlemi: {0}", X + Y);
}

public void Cikar(int X, int Y)
{
Console.WriteLine("Çıkarma İşlemi: {0}", X - Y);
}

public void Karekok(double X)
{
Console.WriteLine("Kare Kök İşlemi: {0:N2}", Math.Sqrt(X));
}
}

static void Main(string[] args)
{
Islemler islem = new Islemler();

Action action = delegate() { islem.Cikar(10, 5); };
action();

action = delegate() { islem.Karekok(10d); };
action();

action = delegate() { islem.Topla(15,15); };
action();
}

Hesapmakinesinin fonksiyonlarının tanımlı olduğu Islemler sınıfının method’larını Action delegate’imize tanımladık. Burda yine .NET 3.0 ile gelen Anonymous delegate’lerden faydalandık.
Örnek çok etkil olmadı ama en azından kullanımı ve ne işe yaradığı konusunda bilgi veriyor. Sonuçta farklı isimlerde ve farklı signature’da methodları tek bir delegate ile çalıştırabiliyoruz.
Action’a method tanımlamasını Lambda kullanarak aşağıdaki şekilde de yapabiliyoruz ve hatta yazının sonuna doğru biraz daha değişik syntax’ta Action tanımlaması yaptım.

Islemler islem = new Islemler();

Action action = () => islem.Cikar(10, 5);
action();

Şimdi biraz daha seksi bir senaryo ele alalım.

Örneğin: Birçok method’unuzun içerisinde hep aynı pattern’i kullanacaksınız. Tüm methodlarınız farklı işler yapacak, farklı tipten ve farklı sayıda parametreler alıyor olacak.
Bu methodlarınız içinde hep aynı işlem kalıbını (pattern’ini veya rutini) kullanmanız gerektiğini varsayalım.
Bu methodların her birine ayrı ayrı belirlediğiniz pattern’i yazmak yerine Action delegate’ini kullanarak global bir method üzerinden pattern’i belirleyip methodlarımızı çağırabiliriz.

Yine işlemler sınıfımız üzerinden örnek vermek gerekirse :

class Islemler
{
public void Topla(int X, int Y)
{
Console.WriteLine("Toplama İşlemi: {0}", X + Y);
}

public void Cikar(int X, int Y)
{
Console.WriteLine("Çıkarma İşlemi: {0}", X - Y);
}

public void Karekok(double X)
{
Console.WriteLine("Kare Kök İşlemi: {0:N2}", Math.Sqrt(X));
}
}

static void Main(string[] args)
{

Islemler islem = new Islemler();
Exception ex = null;
var action = new Action(() => islem.Cikar(10, 10)); //Syntax'ı bu şekilde de olabiliyor ;)
bool state = GlobalInvoker(action, out ex);

if (state)
Console.WriteLine("Gerçekleşti");
else
Console.WriteLine("Gerçekleşmedi: {0}", ex.Message);
}


static bool GlobalInvoker(Action action, out Exception ex)
{
bool cstate = true;

try
{
action();
ex = null;
}
catch (Exception e)
{
ex = e;
cstate = false;
}

return cstate;
}

İşte gördüğünüz gibi GlobalInvoker methodunun içindeki tek bir desen ile tüm methodların düzgün çalışıp, çalışmadığını anladık ve hatta çalışmıyorsa debug için Exception’ımızı da sakladık.

Normalde Action delegate’ini kullanmasaydık tüm method’larımız bool değer döndürecekti ve hepsinde try-cacht blog’u kullanacaktık. Buda ek kod yazmamıza ve tabiki ek zamana mal olacaktı.
Birde bu class’ın 100 kadar method’u olduğunu düşünün!! Abov!

Yorum Bırak

Comment