Try-Catch-Finally blokları ile çalışma anında meydana gelen hataları nasıl yakalayabileceğimizi ve türlerine göre nasıl filtreleyebileceğimizi öğrendik. Hataların türlerine göre filtrelenmesi işleminde bazen Catch bloklarının sayısı bir hayli fazla olabilmekte.
public class ExampleClass { public void ExampleMethod_1() { try { // Metodun Görevi } catch (ArgumentNullException ex) { } catch (IndexOutOfRangeException ex) { } catch (FormatException ex) { } catch (OverflowException ex) { } catch (Exception ex) { } } public void ExampleMethod_2() { try { // Metodun Görevi } catch (ArgumentNullException ex) { } catch (IndexOutOfRangeException ex) { } catch (FormatException ex) { } catch (OverflowException ex) { } catch (Exception ex) { } } } class Program { static void Main(string[] args) { ExampleClass exampleClass = new ExampleClass(); exampleClass.ExampleMethod_1(); exampleClass.ExampleMethod_2(); } }
ExampleClass sınıfının içerisinde tanımlanmış olan ExampleMethod_1 ve ExampleMethod_2 metotlarını inceleyecek olursak; Catch bloklarından dolayı metotların gövdesinde kod kalabalığı oluştuğunu görebiliriz. Üstelik henüz metodun görevini ve Catch bloklarının içeriğini yazmadık bile! ExampleMethod_1 ve ExampleMethod_2 gibi içerinde bir çok Catch bloğu barındıran, onlarca metodun oluşturduğu bir sınıftaki kod kalabalığını tahmin edebilirsiniz.
Tüm metotlarda Try-Catch-Finally bloklarını tekrar tekrar yazmak yerine, oluşan hataları yakalayan ve türlerine göre filtreleyen merkezi bir İstisnai Durum Yönetimi metodu oluşturarak, kod kalabalığını ciddi anlamda azaltabiliriz. Bunun için öncelikle yukarıdaki ExampleClass sınıfımızı Try-Catch bloklarından arındırıp, geriye sadece metotların görevlerini yani metotlar çağrıldığında çalışmasını istediğimiz kodları bırakıyoruz.
public class ExampleClass { public void ExampleMethod_1() { // Metodun Görevi } public void ExampleMethod_2() { // Metodun Görevi } }
ExampleClass sınıfındaki Try-Catch bloklarını kaldırarak kod kalabalığını ciddi anlamda azalttık. Şimdi, ExampleMethod_1 ve ExampleMethod_2 metotlarının çalışması esnasında ortaya çıkan hataları yakalayan ve türlerine göre filtreleyen metodumuzu yazıyoruz.
static void ExceptionCatcher(Action action) { try { action.Invoke(); } catch (ArgumentNullException ex) { } catch (IndexOutOfRangeException ex) { } catch (FormatException ex) { } catch (OverflowException ex) { } catch (Exception ex) { } }
Oluşturduğumuz ExceptionCatcher metodunu dikkatlice inceleyecek olursak; Action türünde bir parametre aldığını görebiliriz. Bu da şu anlama geliyor; biz ExceptionCatcher metoduna parametre olarak bir metot veya kod bloğu gönderebiliriz (Delegate’leri anlatacağım içeriklerde bu konuya daha detaylı bir şekilde değineceğim).
ExceptionCatcher metoduna parametre olarak gönderdiğimiz metotları Invoke() ile çağırmaktayız. Yani toparlayacak olursak; ExceptionCatcher metoduna parametre olarak ExampleMethod_1 ve ExampleMethod_2 metotlarını göndereceğiz ve Invoke() metodu ile bu metotları Try bloğu içerisinde çalıştırıp, hata oluşması durumunda da Catch blokları ile filtreleyeceğiz.
public class ExampleClass { public void ExampleMethod_1() { // Metodun Gövdesi } public void ExampleMethod_2() { // Metodun Gövdesi } } class Program { static void Main(string[] args) { ExampleClass exampleClass = new ExampleClass(); ExceptionCatcher(() => { exampleClass.ExampleMethod_1(); }); ExceptionCatcher(() => { exampleClass.ExampleMethod_2(); }); } static void ExceptionCatcher(Action action) { try { action.Invoke(); } catch (ArgumentNullException ex) { } catch (IndexOutOfRangeException ex) { } catch (FormatException ex) { } catch (OverflowException ex) { } catch (Exception ex) { } } }
Son olarak ExceptionCatcher metoduna parametre olarak bir metot göndermek yerine, bir kod bloğu göndereceğimiz farklı bir örnek yapalım.
class Program { static void Main(string[] args) { ExceptionCatcher(() => { Console.Write("Birinci sayıyı giriniz: "); int sayi_1 = Convert.ToInt32(Console.ReadLine()); Console.Write("İkinci sayıyı giriniz: "); int sayi_2 = Convert.ToInt32(Console.ReadLine()); double sonuc = sayi_1 / sayi_2; Console.WriteLine("Birinci sayının ikinci sayıya bölümü:{0}", sonuc); }); } static void ExceptionCatcher(Action action) { try { action.Invoke(); } catch (FormatException exception) { // Klavyeden sayı yerine harf veya karakter girildiğinde bu catch bloğu çalışacak. Console.WriteLine("Hata! Sadece sayı girilebilir. Hata Mesajı:{0}", exception.Message); } catch (DivideByZeroException exception) { // sayi_2 değişkenine sıfır değeri atandığında bu catch bloğu çalışacak. Console.WriteLine("Hata! Bir sayının sıfıra bölümü sonsuzdur. Hata Mesajı:{0}", exception.Message); } catch (Exception exception) { // Öngördüğümüz hatalar haricinde bir hata oluştuğunda bu catch bloğu çalışacak. Console.WriteLine("Beklenmedik bir hata oluştu. Hata Mesajı:{0}", exception.Message); } } }
Yukarıdaki uygulamamızda ExceptionCatcher metoduna parametre olarak bölme işlemini gerçekleştiren kod bloğunu gönderdik. Göndermiş olduğumuz kod bloğu ExceptionCatcher metodunun Try bloğunda çalışacaktır. Klavyeden sayı yerine harf veya karakter girildiğinde veya sayi_2 değişkenine sıfır değeri atandığında oluşacak hatalar ilgili Catch bloğu tarafından yakalanacaktır.
Serdar YILMAZ