Makale Özeti

Tüm yazılımcı arkadaşlara selamlar, Bu makalemde .NET Framework İstisnai Durumları ve C# dili ile istisnai durum yönetimi konularından bahsedeceğim.

Makale

Tüm yazılımcı arkadaşlara selamlar,

Bu makalemde .NET Framework İstisnai Durumları ve C# dili ile istisnai durum yönetimi konularından bahsedeceğim.

İstisnai Durum nedir?

İstisnai durumlar programların çalışma zamanında hata üretmeleri veya kodda beklenmedik durumların oluşması sonucunda CLR tarafından üretilirler. 

C dili gibi makinaya yakın dillerde bu tür hata kontrol mekanizmaları mevcut değildi.Visual Basic veya benzeri programcıya yakın dillerde hataları yönetmek için çeşitli mekanizmalar mevcuttur.

"Peki C# hata yönetiminin farkı nedir?" dediğinizi duyar gibiyim.

Cevap, C# ile ilk tanışmanızdan itibaren duyduğunuz C# dilinin %100 nesneye yönelik bir dil oluşu olacaktır.Somut bir örnek vermemiz gerekirse, C# ile istisna sınıflarını kullanarak kendi istisna sınıflarımızı oluşturabiliriz.

.NET Framework'ünde istisnai durumlar Exception ile tanımlanırlar ve Exception sınıfından türeyen objelerle yönetilirler.Bunun yanısıra C# %100 oop tabanlı bir dil olduğundan dolayı Object sınıfından türeyen herhangi bir sınıf Exception sınıfı olarak kullanılabilir.

Bu kadar soyut kavramdan sonra isterseniz istisnai durumların C# dilindeki yazım kurallarından nasıl yönetildiğinden bahsedelim.

Yazım kuralı

try
{
    //İstisnai durum oluşturabilecek kod
}
catch(OverflowException e)
{
    //OverflowException İstisnai durum oluştuğunda çalışacak kod
}
catch(<Spesifik İstisnai durum sınıfı> e)
{
    //Spesifik İstisnai durum oluştuğunda çalışacak kod
}
catch(Exception e)
{
    //Genel İstisnai durum oluştuğunda çalışacak kod
}
finally
{
    //İstisnai durum oluşsun veya oluşmasın çalışacak kod.
}

İstisnai durumu yaratabilecek kod try bloğu içine yazılır.Catch bloğunda ise istisnai durum oluştuğunda yapılması gereken işlemlere ait kod bulunur..NET framework'ünde Exception sınıfından türemiş olan spesifik hatalara yönelik istisnai durum sınıfları mevcuttur.Bu sınıfları birden fazla catch bloğunda tanımlayarak oluşacak hatayı klasifike edebiliriz.Finally bloğu içindeki kod ise istisnai durum oluşsun veya oluşmasın çalışacak koddur.

Hernekadar istinai durum yaratabilecek kodu try bloğu içinde yazıyor olsak da CLR programın herhangi bir noktasında istisnai durumlar yaratabilir.Elimizde olmayan sebeplerden dolayı sistem kaynakları kritik durumlara düşebilir, OutOfMemoryException istisnai durumu veya yazdığımız kodun bir metodu tekrarlı bir şekilde kendini çağırması sonucu StackOverflowException istisnai durumu oluşabilir.

Try bloğundan sonra catch veya finally bloklarından biri gelmelidir.


İlk try-catch'imiz
Aşağıdaki örneğimizi inceleyelim.

using System;
namespace Exceptions
{
    class Class1
    { 
        static void Main(string[] args)
        {
            try
            {
                int b=50000;
                short a=0;
                a=Convert.ToInt16(b);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
Value was either too large or too small for an Int16.
Press any key to continue

Try bloğu içinde Int16 türünden olan yani pozitif sınırı 32767 olan bir değişkene 50000 değerini atamaya çalışıyoruz.Dolayısı ile istinai durumumuz oluşuyor.Catch bloğunda ise oluşan istisnai durumun ürettiği mesajı kullanıcıya gösteriyoruz.  

İstisnai durum yaratma - Throw
Satış amaçlı veya diğer yazılım geliştiriciler için geliştirdiğimiz bileşenlerde ilgili iş kurallarına ters düşen durumlarda istisnai durumlar fırlatmamız gerekebilir.C# dilinde istisnai durum fırlatmak için throw komutu kullanılır.

using System;
namespace Exceptions
{
    class Class1
    { 
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                throw new Exception("Hata oluştu");
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
Hata oluştu
Press any key to continue


Exceptions sınıfını kullanarak kendi istisnai durum sınıflarımızı yaratmak
Geliştiridiğimiz proje'nin konusu ve yapısı gereği kendi istisnai durumlarımızı oluşturmamız gerekebilir.Bu tür durumlarda .NET Framework'ü ile birlikte gelen Exceptions sınıfını kullanarak kendi istisnai durum sınıflarımızı yaratabilir bunları projemizde kullanabiliriz.

using System;
namespace Exceptions
{
    public class BizimException:Exception 
    {
        public BizimException(String message) : base (message) 
        {
        }
        public BizimException(String message, Exception inner) : base(message,inner) 
        {
        }
    }
    class Class1
    { 
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                throw new BizimException("Hata oluştu");
            }
            catch(BizimException e)
            {
                Console.WriteLine("Bu bizim yarattığımız özel exception sınıfı hatası : " + e.Message);
            }
            catch(Exception e)
            {
                Console.WriteLine("Bu genel exception sınıfı hatası : " + e.Message);
            }
        }
    }
}
Bu bizim yarattığımız özel exception sınıfı hatası : Hata oluştu
Press any key to continue

Exceptions sınıfının 3 yapıcı metodu mevcuttur.İlk metod hata mesajını string türünden bir parametre ile kabul eder, ikincisi hata mesajı ile birlikte bir üst istisnai durumu Exception obje türünden kabul eder.(inner parametresinin tam olarak ne işe yaradığını ilerleyen satırlarda daha iyi anlayacaksınız).Üçüncü ve son metod ise herhangi bir parametre almaz.

Exceptions Sınıfı 
Şimdi isterseniz Exception sınıfının üyelerini inceleyelim.

StackTrace
Hatanın nerede oluştuğunun detaylı bilgisini içerir.Kaynak dosya ismi ve hatanın oluştuğu satır numarasını verir.

using System;
namespace Exceptions
{
    class Class1
    { 
        static void Main(string[] args)
        {
            try
            {
                int b=50000;
                short a=0;
                a=Convert.ToInt16(b);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.StackTrace.ToString());
            }
        }
    }
}
at System.Convert.ToInt16(Int32 value)
at Exceptions.
Class1.Main(String[] args) in c:\c#\alllabs\exceptions\class1.cs:line 13
Press any key to continue

InnerException
Bazı zamanlar catch bloğuna yazdığımız kodda da hatalar oluşabilir.Bu tür durumlarda oluşan istisnai durumun içerdiği diğer istisnai duruma erişmek için innerexception üyesini kullanırız.Biraz havada kaldığının farkındayım, isterseniz örneğimizi inceleyelim.

using System;
public class BizimException:ApplicationException 
{
    public BizimException(String message) : base (message) 
    {
    }
    public BizimException(String message, Exception inner) : base(message,inner) 
    {
    } 
}
public class ExceptionOrnegi 
{
    public void InnerGonder() 
    {
        throw new BizimException("InnerException hatamız");
    }
    public void InnerYakala() 
    {
        try 
        {
            this.InnerGonder();
        }
        catch (Exception e) 
        {
            throw new BizimException("InnerYakala metodunun oluşturduğu hata.",e);
        }
    }
}
public class Test 
{
    public static void Main() 
    {
        ExceptionOrnegi testEx = new ExceptionOrnegi();
        try 
        {
            testEx.InnerYakala();
        }
        catch(Exception e) 
        {
            Console.WriteLine ("Bu catch bloğunda yakalanan hata : {0}", e.Message);
            Console.WriteLine ("Bu catch bloğundaki e Exception sınıfının innerexception değeri : {0}",e.InnerException);
        }
    }
}
Bu catch bloğunda yakalanan hata : InnerYakala metodunun oluşturduğu hata.
Bu catch bloğundaki e Exception sınıfının innerexception değeri : BizimException: InnerException hatamız
at ExceptionOrnegi.InnerGonder() in c:\c#\alllabs\exceptions\class1.cs:line 15
at ExceptionOrnegi.InnerYakala() in c:\c#\alllabs\exceptions\class1.cs:line 21
Press any key to continue

Kod biraz karmaşık, kodu kısaca bir şema ile ele alırsak;

İlk olarak Test sınıfımızın Main metodu çalışacak ve yarattığımız textEX isimli ExceptionOrneği türünden sınıfımızın InnerYakala metodunu çağrılacaktır.

InnerYakala metodu ise kendi içinde InnerGonder metodunu çağıracak ve İstisnai durum yönetimimiz bu metodda başlayacaktır.

InnerGonder metodu BizimException türünden "InnerException hatamız" mesaj değeri içeren bir istisnai durum fırlatacaktır.InnerGonder metodu ilk olarak InnerYakala metodundan çağırıldığı ve bu metod try bloğuna tabi olduğu için istisnai durum ilk olarak InnerYakala metodunda bulunan catch bloğunca yorumlanacaktır.

InnerYakala bloğundaki catch kodunda ise yeni bir BizimException türünden bir istisnai durum yaratılıyor fakat dikkat ederseniz 2. yapıcı metod kullanılıyor ve InnerGonder metodunun oluşturduğu hata inner parametresi ile yeni oluşturulan istisnai durum objesine gönderiliyor.

Son olarak imleç bütün bu karmaşanın başladığı yere yani Test sınıfımızın Main metodundaki catch bloğuna ulaşıyor.Catch bloğundaki exception objesi InnerYakala metodunun fırlattığı bir istisna olduğu için mesaj değeri "InnerYakala metodunun oluşturduğu hata." şeklindedir.Bu istisna objesinin inner özelliği sayesinde ise InnerGonder metodunda oluşan istisnai durum objesine erişebiliyoruz.

Aşağıdaki şema örnekteki exception objelerinin değerlerini göstermektedir.

Message
Kullanıcıyı bilgilendirmek üzere hata hakkında detaylı açıklama içerir.

HelpLink
Hata hakkında daha detaylı bilgi veren URL bilgisi barındırır.

Source
Hatayı oluşturan sınıf hakkında bilgi verir.

using System;
namespace Exceptions
{
    class Class1
    { 
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                int b=50000;
                short a=0;
                a=Convert.ToInt16(b);
            }
            catch(OverflowException e)
            {
                Console.WriteLine(e.Source.ToString());
            }
        }
    }
}
mscorlib
Press any key to continue

TargetSite
İstisnai durumu oluşturan metod hakkında bilgi içerir.

using System;
namespace Exceptions
{
    class Class1
    { 
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                int b=50000;
                short a=0;
                a=Convert.ToInt16(b);
            }
            catch(OverflowException e)
            {
                Console.WriteLine(e.TargetSite.ToString());
            }
        }
    }
}
Int16 ToInt16(Int32)
Press any key to continue

Evet bir makalenin daha sonuna geldik.Umarım yararlı olmuştur.
Hepinize mutlu günler dilerim. 

Levent YILDIZ
Gulf Agency Company - TURKEY
IT Manager
MCP
msmoracle@hotmail.com 
levent.yildiz@gacworld.com 
http://www.gacworld.com

Kaynaklar
http://msdn.microsoft.com/