Program yazmanın olmazsa olmazlarından biri olan hata yönetiminin C# ile nasıl yapılacağını biraz irdeleyelim... C# ve Kural Dışı Durum Yönetimi
Bir kural dışı durum (exception) programın normal akışının uygulanamaz olduğu durum, yani bir hatadır. Bir sorgulama sonucunda null değer dönerse, işleme devam etmek mümkün olmayabilir. Bu durum hata değildir. Ama kullanıcı sorgulanacak tablo adını yanlış girmişse, bu durumda bir hata ortaya çıkar. Bu hatalar programcı tarafından koda dahil edilebileceği gibi kullanıcı kaynaklı ya da sistemin normal olmayan şartlara gösterdiği tepkilerden kaynaklanabilir. Her programcı, yazdığı kodun içerisine hataları yakalamak için çeşitli yöntemler ekler. Bu yöntemler spesifik bir hatayı yakalamak için olabileceği gibi (örneğin veritabanında birden fazla kullanıcının aynı kayıda erişmesinden kaynaklanan bir kilit problemi), tasarım zamanında göz önüne alınmayan bir durumu yakalamak için de olabilir. Programda ortaya çıkan bir hata, eğer programcı tarafından kontrol edilmezse, program bir çalışma zamanı hatası verir ve kendini sonlandırır.
Kural dışı durum yönetimi (exception handling) sebebi ne olursa olsun herhangi bir hata oluştuğunda, programın normal bir şekilde çalışmaya devam etmesini sağlamak için uygulanır. C#’da çalışma zamanında oluşan her hata System.Exception sınıfının bir üyesidir. System.Exception sınıfının iki alt kümesi vardır. SystemException ve ApplicationException. SystemException, programın çalışması sırasında ortaya çıkan ve Common Language Runtime tarafından oluşturulan hatalardır. ApplicationException hataları ise programın çerisinde, programcı tarafından ortaya çıkarılan hatalardır.
Exception Sınıfı
C# ekibi işleri kolaylaştırmak amacıyla SystemException sınıfından türetilen standart kural dışı durumlar tanımlamıştır. Bu kural dışı durumlar kendi konuları ile ilgili isim uzaylarında bulunur. Örnek olarak System.Data.SqlClient isim uzayında bulunan SqlDataAdapter’in fırlattığı bir kural dışı durum System.Data.SqlClient.SqlException sınıfından türetilir. Üstelik bu hatalardan hatanın nedenini ve kaynağını bulmak da artık daha kolay çünkü mesajlar eskiye göre oldukça açıklayıcı.
Visual Studio kullanıyorsanız System yazıp noktaya bastığınız anda açılan intellisense penceresinde hemen dört tanımlı exception görürsünüz. ApplicationException, ArgumentException, ArgumentNullException ve ArgumentOutOfRangeException.. Bütün bunlar farklı durumlarda fırlatılmasına rağmen hepsinin özellik ve yöntemleri aynıdır. Bu özelliklerin en önemlilerine birlikte bakalım
HelpLink: Hatayla ilişkili yardım dosyası.
Message: Hata mesajı
Source: Hatanın kaynağı.
TargetSite: Çok kullanışlı bir özellik, hatanın ortaya çıktığı yordamın adını verir.
StackTrace: Hataya yol açan çağrıların yığınını tutan bir karakter katarı döndürür. Dosya adı, yordam adı ve hatanın oluştuğu satır numarasını belirtir.
Kural Dışı Durumları Yakalamak ve Yönetmek
C#’da kural dışı durumlar dört anahtar kelime ile yönetilir: try, catch, throw ve finally. Şimdi bunları kullanımını görelim.
Try-catch : Bu blok C# altında hata yakalamanın temeli gibidir ve bu anahtar kelimeler birbirinden ayrı kullanılamaz. En basit kullanımı şu şekildedir.
try
{
// Hata kontrolünün yapılacağı kodlar
}
catch (KuralDisiDurumTipi KuralDisiDurumDegiskeni)
{
// Hata ortaya çıktığında yapılacak işlemler
}
Kural dışı durum tipi, CLR tarafından fırlatılan durum tipidir ve Kural Dışı Durumlar bölümünde belirtilen değerlerden birini alır. Kural dışı durum değişkeni de, bizim hatayı ele alırken kullanacağımız hata nesnesidir. Gerçek bir örnek:
using System;
class Test
{
[STAThread]
static void Main(string[] args)
{
int[] dizi=new int[4];
try
{
Console.WriteLine("İşlem başlıyor...");
for (int i=0; i<=10; i++)
{
dizi[i]=i;
Console.WriteLine("dizi[{0}] : {1}",i,dizi[i]);
}
Console.WriteLine("İşlem hatasız tamamlandı...");
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("Hata oluştu : " + e.Message);
}
Console.ReadLine();
}
}
Çıktı
İşlem başlıyor…
dizi[0] : 0
dizi[1] : 1
dizi[2] : 2
dizi[3] : 3
Hata oluştu : Index was outside the bounds of the array.
Burada döngü içerisinde, diziye üst sınırdan daha fazla sayıda eleman aktarılarak bir hata oluşturuluyor. Döngünün ilk dört adımında herhangi bir problem olmadığı için program düzgün bir şekilde çıktı üretiyor. 5. adımda dizinin üst sınırı aşıldığı için bir hata ortaya çıkıyor ve bu hata catch bloğu ile yakalanıyor. Hatanın ortaya çıktığı andan itibaren try bloğu içerisindeki kodların yürütülmesi sona eriyor ve catch bloğu içerisindeki kodlar yürütülüyor. Burada for döngüsünden sonraki Console.WriteLine satırının yürütülmediğine dikkat edin. Eğer döngüyü 3 e kadar devam ettirirseniz, hata olmayacağı için for döngüsünden sonraki Console.WriteLine satırı da yürütülecekti.
Finally : finally, try - catch bloğunun sonunda, hata olsun olmasın yürütülmesini isteğimiz kod blokları için kullanılır. Örnek olarak bir veritabanı bağlantısı kullanalım. Hata olsun ya da olmasın yapacağımız işlemler sonucunda veritabanı bağlantısını kapatmak isteriz. Bu durumda finally imdadımıza yetişir. İşte bir örnek:
try
{
SqlConnection cn=new SqlConneciton();
// veritabanina baglanmaya calis..
}
catch (System.Data.SqlClient.SqlExceptiom e)
{
MessageBox.Show(“Veritabanina baglanti kurulamadı”;
}
finally
{
cn.Close();
}
Bu durumda hata olsa da olmasa da cn nesnesinin kapatılmasını garanti ederiz.
Throw: Program içerisinde herhangi bir yerde bir kural dışı durum fırlatmak istediğimizde throw kullanırız. Kullanımı throw KuralDisiDurumTipi seklindedir. Aşağıdaki örnek bir sıfıra bölünme hatası fırlatır:
using System;
class Test
{
[STAThread]
static void Main(string[] args)
{
try
{
Console.WriteLine("Birinci satır, hata yok");
throw new DivideByZeroException();
Console.WriteLine("İkinci satır, ekranda gözükmez...");
}
catch (DivideByZeroException e)
{
Console.WriteLine("Üçüncü satır, hata oluştu : " + e.Message);
}
}
}
Bu kodu yazdığınızda Visual Studio throw’dan sonraki Console.WriteLine satırında sizi ulaşılamayan kod mesajıyla uyarır.
Çıktı:
Birinci satır, hata yok
Üçüncü satır, hata oluştu : Attempted to divide by zero.
Try-catch kullanım örnekleri
Yukarıdaki örnekler sadece bir tek hata durumu içindi. İndeksin sınırlar dışına çıkması ya da sıfıra bölme gibi. Normal olarak yazdığımız programlarda birden fazla hata durumuyla karşılaşabiliriz. Bu durumda yapacağımız şey tek bir try bloğuna karşılık istediğimiz sayıda catch bloğu yazmaktır. Bu durumda bir hata oluştuğunda, oluşan hatanın tipine uygun olan catch bloğu yürütülecektir. İşte örnek:
using System;
class Test
{
[STAThread]
static void Main(string[] args)
{
int[] bolunen={2,4,6,8,10,12,14};
int[] bolen={1,2,0,4,0};
for (int i=0; i<bolunen.Length;i++)
{
try
{
Console.WriteLine(bolunen[i] +" / "+ bolen[i] +" = " +bolunen[i]/bolen[i]);
}
catch (DivideByZeroException)
{
Console.WriteLine("Sıfıra bölme hatası oluştu..");
}
catch(IndexOutOfRangeException)
{
Console.WriteLine("Dizi üst sınırı aşıldı...");
}
}
}
}
Çıktı:
2 / 1 = 2
4 / 2 = 2
Sıfıra bölme hatası oluştu..
8 / 4 = 2
Sıfıra bölme hatası oluştu..
Dizi üst sınırı aşıldı…
Dizi üst sınırı aşıldı…
[COLOR=#c5003f]Peki tüm hatalar için tek tek catch blokları mı yazmak zorundayız? Neyse ki hayır… Eğer catch bloğunda herhangi bir hata tipi belirtmezsek, oluşan hata ne olursa olsun yakalanır…
try
{
// Hata kontrolünün yapılacağı kodlar
}
catch
{
// Bu şekilde bir kullanım ile tüm hataları yakalarız…
}
C# ve Kural Dışı Durum Yönetimi
C# ve Kural Dışı Durum Yönetimi
Konuyu Okuyanlar: 1 Ziyaretçi