Local Functions Method içinde Method Tanımlama
Selamlar,
Bu makale C#7.0’da olması muhtemel Yerel Fonksiyon kavramına deyineceğiz. Yani bir method içine tanımlanabilecek fonksiyonlar ve faydalarından bahsediceğiz. Bu yazıda anlatılanlar şu anki C# sürümünde yoktur. Bir sonraki C# 7.0’da ola da bilir, olmaya da bilir. Sizin de fikriniz ya da bu şekilde de kullanılabilir dediğiniz bir durum olur ise lütfen paylaşmaktan çekinmeyin. Ben method içine tanımlanabilecek bir fonksiyonun kullanışlı olabileceği bir kaç senaryo oluşturdum. Şimdi gelin hep beraber bunları inceleyelim.
- İlk senaryoda Ürünler ve Stok bilgisinin tutulduğu 2 farklı dizi düşünelim. Bu listede ürünler ve stok ayını dizi sırasında ilerlemektedir. İlk diziden ürün bilgisi, ikinci diziden ürün stok bilgisi alınmaktadır.
1 2 3 4 5 6 7 8 9 |
public static IEnumerable<TProductList> GetAllProductsStock<T1, T2, TProductList>(IEnumerable<T1> product, IEnumerable<T2> stock, Func<T1, T2, TProductList> Report) { var e1 = product.GetEnumerator(); var e2 = stock.GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) yield return Report(e1.Current, e2.Current); } |
Yukarıda görüldüğü “GetAllProductStock()” adında bir method 3 parametre almaktadır.
- 1. parametere List<product>
- 2. parametre List<stock>
- 3.parametre Report() adında bir function’dır.
Her iki dizi tek tek dönülerek “Report()” methoduna parametre olarak verilerek bir değer döndürülmektedir. Bu durumda eğer ilgili listelerden değer dönmez ise “null” hatası alınır. Aynı zamanda parametre olarak geçilen function da null olabilir. Bu durumda aşağıdaki gibi bir kontrol yapmak ve geri dönüş için ayrı bir method oluşturmak bu sorunu çözebilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public static IEnumerable<TProductList> GetAllProductsStock<T1, T2, TProductList>(IEnumerable<T1> product, IEnumerable<T2> stock, Func<T1, T2, TProductList> Report) { if (product== null) throw new NullReferenceException("product null olamaz!"); if (stock== null) throw new NullReferenceException("stock null olamaz!"); if (Report== null) throw new NullReferenceException("Report null olamaz!"); return RunReport(product, stock, Report); } private static IEnumerable<TProductList> RunReport<T1, T2, TProductList>(IEnumerable<T1> product, IEnumerable<T2> stock, Func<T1, T2, TProductList> Report) { var e1 = product.GetEnumerator(); var e2 = stock.GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) yield return Report(e1.Current, e2.Current); } |
Local Function kullanarak tam bu noktada okunurluğu arttıralım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public static IEnumerable<TProductList> GetAllProductsStock<T1, T2, T3, TProductList>(IEnumerable<T1> product, IEnumerable<T2> stock, Func<T1, T2, TProductList> Report) { if (product == null) throw new NullReferenceException("product null olamaz!"); if (stock== null) throw new NullReferenceException("stock null olamaz!"); if (Report== null) throw new NullReferenceException("Report null olamaz!"); //Burası Local Function'ın Method içinde Fonkiyon'un tanımlandığı yerdir! IEnumerable<TResult>RunReport() { var e1 = product.GetEnumerator(); var e2 = stock.GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) yield return Report(e1.Current, e2.Current); } return RunReport(); } |
- Local Function(Yerel Fonksiyon) hiçbir parametre almamıştır.
- “GetAllProductsStock()” tüm değişkenleri ve “Yerel Function”‘ı kapsamaktadır. Böylece tanımlanması gereken değişken ve hata olasılığı minimum’a indirilmiştir.
- Tüm kontrol işlemleri Ana Method olan “GetAllProductsStock()” methodunda yapılmakta ve öteleme işlemi “Local Function”‘da gerçekleştirilmektedir.
2. İkinci senaryoda “WaitForaWhile()” methodunda belirtilen sürenin belirli bir katsayısı kadar asenkron olarak bekletilip, geçen toplam süre geri dönülmektedir.
1 2 3 4 5 6 7 8 9 10 11 |
public static async Task<int> WaitForaWhile(int time) { if (time < 0) throw new ArgumentOutOfRangeException("Süre 0'dan küçük olamaz!"); if (time> 50) throw new ArgumentOutOfRangeException("Bekleme soresi çok uzun!"); await Task.Delay(time * 500); return time * 500; } |
Kodu aşağıdaki gibi değiştirdiğimizde methodun çağrılma esnasında asenkron yapısı yüzünden hata alırız. Bunun için “DelayJob()” methodu başına “await” yazılıp beklenmeli ve “WaitForWhile()” methodunun başına da “async” yazılmalıdır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public static Task<int> WaitForaWhile(int time) { if (time < 0) throw new ArgumentOutOfRangeException("Süre 0'dan küçük olamaz!"); if (time> 50) throw new ArgumentOutOfRangeException("Bekleme soresi çok uzun!"); return DelayJob(time); } private static async Task<int> DelayJob(int time) { await Task.Delay(time* 500); return time* 500; } |
Bazı durumlarda methodlar asenkron yapıyı desteklemeyebilirler yada çağrıldıkları tüm methodların da asenkron hale getirilmesi gerekmektedir. İç içe sarmal 10 katmanlı bir yapıda tüm katmanların böyle bir durumda güncellenmesi gerekmektedir. İlgili durum aşağıdaki “Local Function” ile ortadan kaldırılabilir. Böylece ilgili method altında tanımlanan function sayesinde var olan “WaitForWhile()” methodu ve varsa bunu kullanan diğer methodlar değişmeden kalırlar. Sadece local tanımlanan function “async” yapılarak çözüme gidilebilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public static Task<int> WaitForaWhile(int time) { if (time< 0) throw new ArgumentOutOfRangeException("Süre 0'dan küçük olamaz!"); if (time> 50) throw new ArgumentOutOfRangeException("Bekleme soresi çok uzun!"); async Task<int> AsyncPart() { await Task.Delay(time* 500); return time* 500; } return AsyncPart(); } |
“Local Functionlar” ilerde gelir mi yoksa gelmez mi şu an için belirsiz ama bence sırf bu seneryolar için bile bir ilaç. Ayrıca kodun okunurluğunun arttırılması ve yazımdaki sadelik cabası. Başta da söylediğim gibi sizin de aklınıza kullanılabileceği başka durumlar gelirse lütfen paylaşmaktan çekinmeyin.
Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hoşçakalın.
Source: Bill Wagner’in makalesi kaynak alınarak yazılmıştır. http://thebillwagner.com/
Son Yorumlar