İstisna (Exception)kavramı programlama açısında büyük bir önem taşımaktadır.
Bütün gelişmiş programlama dillerinde istisnaları yönetmek için çeşitli
yöntemler ortaya konulmuştur. Bu yöntemler birçok açıdan benzerlikler gösterse
de, çeşitli farklılıklar da bulunmaktadır. Öncelikle istisna kavramını bir
inceleyelim.
İstisnalar, programımızın çalışma zamanında yani program çalışırken
ortaya çıkan olağan dışı durumlardır. Programcılık dilinde "programın kırılması"
ile adlandırılan olaylarda aslında bir istisnanın meydana geldiğini
göstermektedir. Örneğin bir sayının sıfıra bölünmesi
"DivisionDivideByZeroException" istisnasının ortaya çıkmasına sebep
olmaktadır. Başka bir istisna örneği ise uyumsuz tipler arasında değer aktarımı
gerçekleştirmeye çalışmaktır. Bir programcı olarak kod üzerinde her ne kadar
detaylı çalışma yapsakta kullanıcı faktörü göz önüne alındığında çalışma zamanı
hatalarının ( Runtime Error ) ortaya çıkması olasıdır. Aşağıdaki örneğimiz, çalışma
zamanında ortaya çıkabilecek bazı istisnaları göstermektedir.
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
sonuc = int.Parse("selam"); // Tür dönüşüm hatası
myobj.ToString(); // Null referance hatası
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
sonuc = int.Parse("selam"); // Tür dönüşüm hatası
myobj.ToString(); // Null referance hatası
}
}
}
Bu ve benzeri bir çok hata .NET platformu tarafından izlenmekte ve
gerekli istisnalar ortaya çıkartılmaktadır. İstisnalar iki şekilde ortaya çıkar.
1. Yazılım geliştirici "throw" ifadesini kullanarak kendi
istisnası ortaya çıkartabilir.
2. Yukarıdaki örneklerimizde de ortaya çıkan ve programımızın normal olarak devamını sürdürmesini engelleyecek hatalardır.
2. Yukarıdaki örneklerimizde de ortaya çıkan ve programımızın normal olarak devamını sürdürmesini engelleyecek hatalardır.
Bu makalemizde programımızın normal işleyişini bozan istisnaları
yönetmeyi inceleyeceğiz. Bu noktada unutulmaması gereken ilk nokta istisna
yönetimi performans açısından pahalı bir seçenektir. Bu nedenle programcılıkta
ilk seçeneğimiz programımıza giriş yapan bütün değerleri maskeleme, büyüklük
ölçümü, tip uyum denetimlerini gibi mekanizmalarla denetlemektir. Gereksiz yere
kullanılacak istisna yönetimi büyük performans kayıplarına neden olmaktadır.
.NET ortamında her şey gibi istisnalarda sınıflar kullanılarak oluşturulmakta
ve tüm istisnalar temel System.Exception nesnesinden
türetilmektedir. Farklı istisnalar için farklı sınıflar bulunmaktadır. Bu
istisna sınıfları veritabanı istisnalarından bellek istisnalarına kadar her
alanda bulunmaktadır. Her istisna sınıfı kendine özgü bazı bileşenleri
bünyesinde barındırmaktadır.
İstisnaları ortaya çıkartmak ve bu istisnaları yakalayıp yönetmek ayrı işlerdir.
Bu makalemizde ortaya çıkmış olan istisnaları yakalamayı ve yönetmeyi işleyeceğiz.
Bir istisnayı yakalamak için öncelikle istisnanın ortaya çıkabileceği kod aralığını
tespit etmek gerekir. Bu işlem gerçekleştirildikten sonra aşağıdaki ifadelerden
birini kullanarak istisna yakalama işlemi gerçekleştirilir.
1. try catch
2. try finally
3. try catch finally
try catch:
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
try
{
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
try
{
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Try Catch ifadelerinde örneğimizde de gördüğümüz gibi istisnanın ortaya
çıkması muhtemel olan kod alanı try{......}catch parantezleri arasına alınmıştır.
Bu kod artık izlenmektedir. Peki bir istisna ortaya çıktığı zaman nasıl bir
olay meydana gelecektir. Parantez içerisinde bir hata meydana geldiğinde; hatanın
ortaya çıktığı noktadan sonraki kodlar işleme konulmaz ve parantezden sonraki
kod işleme alınır. Yukarıdaki örneğimizde Console.WriteLine("Hiç
Bir Hata Oluşmadı"); kod satırı işleme
konulmadan catch ifadesine
atlanır. catch ifadesi adındanda anlaşılacağı gibi istisnaların yakalanıp
seviyelendirildiği alandır. Daha öncede bahsettiğimiz gibi bütün istisna
nesneleri Exception sınıfından türetilmiştir. Bu nedenle bütün hatalar
Exception nesnesi tarafından yakalanabilmektedir. Exception sınıfı bünyesinde
çeşitli özellik ve metotlar barındırmaktadır. Bu özelliklerden en önemlisi
Message özelliğidir. String tipinde olan bu özellik istisna sonucu üretilen
bilgi mesajını içermektedir. Yukarıda ki örneğimizde Attempted Divide by
Zero bilgi mesajı ortaya çıkmaktadır. Peki bu try {..} bloğu içinde bir kaç
çeşit hata meydana gelse ve bu hatalardan istediğimizi yakalamak istersek ne
yapmamız gerekir.
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
string txt;
try
{
txt = Console.ReadLine();
sayi2 = int.Parse(txt);
int sonuc = 0;
sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] args)
{
int sayi1 = 25;
int sayi2 = 0;
string txt;
try
{
txt = Console.ReadLine();
sayi2 = int.Parse(txt);
int sonuc = 0;
sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
catch (DivideByZeroException e)
{
Console.WriteLine(e.Message);
}
catch (FormatException e)
{
Console.WriteLine(e.Message);
}
}
}
}
Yukarıdaki örneğimizde
try{} bloğu içinde 2 çeşit hata ortaya çıkma ihtimali vardır. Bunlardan
birincisi klavyeden girilen değerin int.Parse(txt) metodu ile stringten
integer türüne dönüşümünde alfanümerik karakterlerden dolayı FormatException
istisnanıs ve ikincisi girilen değerin 0 olması durumunda DivideByZeroException
istisnasının ortaya çıkmasıdır. Örneğimizde de görüldüğü gibi programımız farklı
hatalar için farklı davranmasını istiyorsak hata yakalama işini bir kaç
seviyede gerçekleştirerek amacımıza ulaşabiliriz. Burda dikkat edilmesi gereken
nokta özel olarak seçilen istisna sınıfları dışında örneğin yukarıda bir
nullreferance gibi bir hata oluştuğu taktirde yakalanamayacak olduğudur. Bütün
hataları yakalamak gereken durumlarda Exception temel sınıfını kullanmak
gereklidir.
try finally:
İstisna
takibinde Try finally bloğunun özelliği; hata ortaya çıksa da çıkmasa da bu finally
bloğunun çalışıyor olmasıdır. Try{} bloğu içerisinde bir istisna ortaya çıktığında
kodumuz aynen try catch ifadesinde olduğu gibi hatanın ortaya çıkmış olduğu
noktadan sonraki kodlar çalışmadan finally bloğuna geçilir. Catch ifadesinden
farklı olarak hatanın çeşidinin tespiti mümkün değildir. Finally bloğu
programlarımızda kullanım sebebi try {} içerisinde yaratmış olduğumuz
nesnelerin sonlandırılması veya değişkenlerin son değerlerinin belirlenmesi
gereken durumlarda kullanılır.
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
int sayi1 = 25;
int sayi2 = 0;
try
{
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
finally
{
Console.WriteLine(e.Message);
}
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
int sayi1 = 25;
int sayi2 = 0;
try
{
int sonuc = 0; sonuc = sayi1 / sayi2; // Sıfıra bölünme hatası
Console.WriteLine("Hiç Bir Hata Oluşmadı");
}
finally
{
Console.WriteLine(e.Message);
}
}
}
}
Bu kullanıma bir örnek vermemiz gerekirse bir veritabanı bağlantısı yapıp
geriye bazı değerler döndüren bir fonksiyon olsun. Bu fonksiyon içerisinde
veritabanı bağlantısı gerçekleştirilip gerekli data çekim işlemleri meydana
geldikten sonra bağlantının kesilmesi gerçekleştirilecektir.
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
DataAl();
}
public string DataAl()
{
string bilgi;
Baglan();
try
{
bilgi = getdata();
}
finally
{
baglantiyikes();
return bilgi;
}
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
DataAl();
}
public string DataAl()
{
string bilgi;
Baglan();
try
{
bilgi = getdata();
}
finally
{
baglantiyikes();
return bilgi;
}
}
}
}
Örneğimizde
benzer bir yapı bulunmaktadır. Yukarıdaki gibi bir yapı veritabanı bağlantısının
kesilecek olması kesindir. Bu yöntemle fazla kaynak kullanımı gibi etkilerden
kurtulmamız mümkündür.
try
catch finally:
try
catch ve try finally ifadelerinin ve kullanım yeteneklerinin birleşerek ortak
bir ifade halini aldığı kullanıma try catch finally diyoruz. Bu yöntem kullanılarak
hatalar izlenip ayıklanabilmekte; bununla birlikte finally bloğunu yetenekleri
kullanılarak kaynak kullanımı denetim altında alınabilmektedir.
using System;
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
DataAl();
}
public string DataAl()
{
string bilgi;
Baglan();
try
{
bilgi = getdata();
}
catch(Exception e)
{
bilgi = e.Message +" Hatası Oluştu";
}
finally
{
baglantiyikes();
return bilgi;
}
}
}
}
namespace Exception1
{
class Istisnalar
{
[STAThread]
static void Main(string[] argös)
{
DataAl();
}
public string DataAl()
{
string bilgi;
Baglan();
try
{
bilgi = getdata();
}
catch(Exception e)
{
bilgi = e.Message +" Hatası Oluştu";
}
finally
{
baglantiyikes();
return bilgi;
}
}
}
}
Hiç yorum yok:
Yorum Gönder