bilgiz.org

C# İle biLGİsayar programlama temelleri (C# Programlama Kitabı) Svetlin Nakov & Co

  • 12.2 İstisnai Durum Nedir
  • 12.2.1 İstisnai Durumlar
  • 12.2.2 İstisnai Durumların Tespiti ve İşlenmesi
  • 12.2.3 Nesne Yönelimli Programlamada İstisnalar
  • 12.2.4 .NET İstisnaları
  • 12.2.5 İstisna Fırlatan Bir Örnek Kod
  • 12.2.6 İstisnalar Nasıl Çalışır
  • 12.2.7 C İstisnalarını Yakalamak
  • 12.2.8 try-catch Programlama Yapısı
  • 12.2.9 İstisnaları Yakalamak - Örnek
  • 12.2.10 Yığıt İzlencesi
  • 12.2.11 Yığıt İzlencesi – Örnek
  • 12.2.12 Yığıt İzlencesini Okuma
  • 12.2.12 İstisnaların Fırlatılması (throw Yapısıyla)



  • Sayfa29/31
    Tarih02.07.2017
    Büyüklüğü3.36 Mb.

    Indir 3.36 Mb.
    1   ...   23   24   25   26   27   28   29   30   31

    Bölüm 12. İstisnai Durum

    İşleme


    12.1 Bölümün İçindekileri


    Bu bölümde nesne yönelimli programlama ve özellikle C# dilinde istisnaları tartışacağız. İstisnai durum işlemek için try-catch yapısının nasıl kullanılacağını, çağıran metotlara istisnaları nasıl bildireceğimizi ve standart yada özel istisnai durumları atamak için throw yapısını nasıl kullanacağımızı öğreneceğiz. İstisnaların kullanıldığı örneklere bakacağız. .NET Çerçevesi içindeki istisna türlerine ve istisna hiyerarşilerine göz atacağız. Bölümün sonunda istisnaları kullanmanın avantajlarını tartışacağız ve bunların en iyi uygulamalarını göreceğiz; istisnaların farklı durumlar için nasıl uygulanabileceğini öğreneceğiz.

    12.2 İstisnai Durum Nedir?


    Yazdığımız bir program zorunlu olmayan, fonksiyonel programlama prensiplerine bağlı kalarak ve çoğu zaman programın normal olarak çalıştırılacağına inanarak kodlanırken, bilgisayarın ne yapacağı adım adım anlatılmalıdır. Gerçekten de, çoğu zaman, program normal kalıpları takip eder, ancak bazı istisnaların oluşması olasıdır. Örneğin, bir dosyayı okumak ve içeriğini ekranda görüntülemek istediğimizi düşünün. Dosyanın uzak sunucuda bulunduğunu varsayın ve okuma işlemi sırasında bir anda bağlantı kesilsin. Dosya sadece kısmen elde edilmiştir. Programın normal çalışması ve dosyanın içeriğini ekranda göstermesi mümkün olmayacaktır. Bu durumda programın normal (ve doğru) çalışması sırasında bir özel durum (istisna) oluşur.

    12.2.1 İstisnai Durumlar



    İstisnai durum, programın çalışması sırasında özel olarak işlenmesi gereken özel durumdur. İstisnalar beklenmedik durumların bulunması ve onlara tepki verilmesi için bir programlama paradigması sağlar. Bir istisna ortaya çıktığında, program durumu kaydedilmelidir, programın normal akışı kesilir ve kontrol bir özel durum işleyicisine geçirilir. İstisna ortaya çıktığında, öncelikle bu durumun belirlenmesi veya kaydedilmesi ve istisna fark edildiğinde kontrolün özel durum işleyicisine geçmesi gerekir.
    Çalıştırılan programda oluşan bir hata yada alışılmadık durum, programlama kodu tarafından sinyal gönderilerek bildirilir veya fırlatılır. Örneğin, eğer varolmayan bir dosyayı açmak isterseniz, dosyayı açmak için sorumlu olan kod bunu algılayacak ve uygun bir hata iletisi bir özel durum fırlatacaktır.
    İstisnalar nesne yönelimli programlamanın (OOP) temel paradigmalarından biridir. Detaylı açıklamalar için bkz. “Nesne Yönelimli Programlamanın İlkeleri” Bölümü.


    12.2.2 İstisnai Durumların Tespiti ve İşlenmesi



    İstisna işleme istisna tespitini ve yakalanmasını sağlayan bir mekanizmadır. CLR (Common Language Runtime) içinde bu mekanizmayı sağlayan bazı C# dil yapıları bulunur. CLR her istisnai durumu ele alan kodu içerir. CLR her istisnayı onu işleyecek koda yönlendirir.


    12.2.3 Nesne Yönelimli Programlamada İstisnalar

    Nesne Yönelimli Programlama’da (OOP) istisnalar, merkezi olarak hata ve istisnai durum işlenmesi için güçlü bir mekanizmadır. Bu mekanizma, hata işleme için düşünülen her fonksiyonun başarılı bir yürütme ya da bir hata kodunu gösterdiği yordam odaklı yöntemleri değiştirir.


    Genellikle OOP kapsamında işlem yürüten bir kod eğer sorun varsa ve işlem başarıyla tamamlanamadıysa istisnaya neden olur. İşleme neden olan metot istisnayı yakalayabilir (ve hatayı işleyebilir) yada çağıran metota istisna iletilir. Böylece hata işlenmesi çağrı yığıtı içinde daha üst düzeye taşınır ve genel olarak hataların ve beklenmedik durumların esnek yönetimini sağlar.
    Bir başka temel kavram istisna hiyerarşisidir. OOP’da istisnaların her biri sınıftır ve hiyerarşileri oluşturmak için kalıtsallıktan faydalanılabilir. Bir istisna işlenirken (algılanırken) işleme mekanizması sadece belirli bir hatayı değil, bütün bir sınıfa ait istisnaları yakalayabilir (geleneksel yordamsal programlar gibi).
    OOP programların yürütülmesi sırasında ortaya çıkabilecek hata durumlarını yada beklenmedik olayları yönetmek için istisnaların kullanılması tavsiye edilir. Bu yordamsal hata işleme yaklaşımını değiştirir ve merkezi, tek bir yerde birden fazla hata işleme ve daha üst bir düzeye hataları geçirme yeteneği gibi önemli avantajlar sağlar. Bir diğer önemli avantajı, istisnaların kendi kendilerini tarif etmesi ve hiyerarşi oluşturabilmeleridir.
    Bazen istisnalar bir sorunu sinyallemek için değil, ancak beklenmeyen bir olayı işlemek için de kullanılır. Bu iyi bir uygulama olarak kabul edilmez, çünkü istisnalar programın normal akışını kontrol etmemelidir. Bu bölümün sonunda bu konuya daha detaylı bakacağız.

    12.2.4 .NET İstisnaları

    .NET istisnası normal program akışında beklenmeyen bir hata yada olayı sinyalleyen bir nesnedir. Böyle bir alışılmadık olay gerçekleştiğinde çalışan metot, hata türü, hatanın program içerisinde oluştuğu yeri, ve yanı sıra hata anında program durumunu ilgilendiren özel bilgileri de içeren bir nesne ‘fırlatır’.


    .NET içerisinde her istisna hatanın kesin olarak nerede oluştuğu konusunda bilgi veren yığıt izlencesini içerir. Daha fazla detay bu bölümün ilerleyen bölümlerinde ele alınacaktır.

    12.2.5 İstisna Fırlatan Bir Örnek Kod



    İstisna fırlatan bir kod örneği aşağıda verilmiştir:


    class ExceptionsDemo

    {

    static void Main()



    {

    string fileName = "WrongTextFile.txt";

    ReadFile(fileName);

    }
    static void ReadFile(string fileName)

    {

    TextReader reader = new StreamReader(fileName);



    string line = reader.ReadLine();

    Console.WriteLine(line);

    reader.Close();

    }

    }


    Bu program çalıştırırsanız, derleme başarıyla gerçekleşir, ancak çalıştırdığınızda sonuç aşağıdaki gibi görünecektir (Döküm sonucunda FileNotFoundException konsolda elde edilmiştir):


    Bu örnekte, bir dosyayı okumak için açmaya çalıştığınız ve sonra ekranda bu dosyanın ilk satırını görüntüleyen bir kod görülüyor. Dosyalar ile çalışma hakkında daha fazla detaylı açıklamalar için bkz. “Metin Dosyaları” Bölümü.



    ReadFile() kodundaki ilk iki satır istisna fırlatan kodu içeriyor. Bu örnekte, eğer WrongFile.txt dosyası bulunmuyorsa, StreamReader(string, fileName) kurucu metotu FileNotFoundException istisnasını fırlatacaktır. Eğer beklenmedik bir sorun, girdi-çıktı işlemleri sırasında oluşursa, ReadLine() gibi akış (stream) metotları IOException istisnasını fırlatacaktır.

    Yukarıdaki kod başarıyla derlenir, ancak çalışma zamanında eğer Wrongtextfile.txt dosyası bulunmuyorsa bir istisna fırlatır. Bu durumda sonuçta bir hata iletisi konsolda görüntülenir. Konsol çıktısı, hatanın oluştuğu yer ve hatanın nasıl oluştuğu hakkında da bilgi içerir.


    12.2.6 İstisnalar Nasıl Çalışır?


    Normal program yürütmesi sırasında bir metot istisna fırlatırsa, programın normal akışı kesilir. Yukarıdaki örnekte bu StreamReader başlatıldığında gerçekleşir. Şu satıra bir göz atalım:

    TextReader reader = new StreamReader("WrongTextFile.txt");

    Eğer bu satır bir hatayı tetiklerse, reader yerel değişkenine ilk değer atanmayacak ve null varsayılan değerine sahip olacaktır. Metotu takip eden hiçbir satır çalıştırılmayacaktır. CLR hatayı işleyen bir işleyiciyi buluncaya dek, program kesintiye uğrar.

    12.2.7 C# İstisnalarını Yakalamak


    Bir metot istisna attıktan sonra CLR hatayı işleyebilecek bir istisna işleyicisini arar. Bunun nasıl çalıştığını anlamak için, çağrı-yığıtı kavramına daha yakından bakacağız. Çağrı-yığıtı programı, metot çağrıları, kendi yerel değişkenleri, metot parametreleri hakkında ve değer türleri için bellek bilgilerini içeren bir yığıt (stack) veri yapısıdır.

    .NET programlarının yürütülmesi hangi programın giriş noktası olan Main(…) metodu ile başlar. Adı "Metot 1" olarak adlandırılabilen başka bir metot, Main içinden çağrılabilir. "Metot 1", "Metot 2"yi çağırsın, ve bu “Metot N”nin çağrılmasına dek devam etsin.

    “Metot N” yürütmeyi bitirdiğinde, program akışı onu çağıran metota geri döner (örneğimizde “Metot N-1” olurdu), bu metot da onu çağıran metota geri dönecektir. Main(…) metotuna ulaşıncaya dek bu böyle devam eder. Main(…) bitirince programın tümü sonlanır.

    Genel prensip ne zaman yeni bir metot çağrılacaksa, yığıtın en tepesine eklenir. Metot tamamlandığında, yığıttan geri çekilir. Herhangi bir anda, çağrı yığıtı yürütülmekte olan tüm metotları içerir. Main(…) metotundan başlayarak, şu anda yerel değişkenleri ve girdi olarak alınan argümanları ile birlikte çalışmakta olan son metota dek.



    İstisna işleme mekanizması tersine bir süreç izler. Bir istisna oluştuğunda, CLR çağrı-yığıtında bir istisna işleyicisi arar. İstisnayı yakalayan bir işleyici bulunana dek, çağrı yığıtının aşağı yerlerinde kalan her metot için bu tekrarlanır. Main(…) metotuna ulaşıldığı zaman hiçbir işleyici bulunmazsa, CLR istisnayı yakalar ve genellikle bir hata iletisi görüntüler (konsolda veya özel bir hata iletişim kutusunda). Açıklanan metot çağrısı ve istisna işleme sürecinin görüntüsü aşağıdaki şemada verilmiştir (1’den 5'e kadar olan adımlar):

    12.2.8 try-catch Programlama Yapısı


    İstisnayı işlemek için, istisnanın oluşabileceği kodu try-catch bloğu ile kuşatmalıyız:

    Try

    {

    // Some code that may throw an exception



    }

    catch (ExceptionType objectName)

    {

    // Code handling an Exception



    }

    catch (ExceptionType objectName)

    {

    // Code handling an Exception



    }

    Try-catch yapısı bir try bloğu ve bir veya birden fazla catch bloğundan oluşmaktadır. Try bloğu içinde istisnaları fırlatabilecek kodu koyuyoruz. Catch bloğu içindeki ExceptionType, System.Exception sınıfından türetilmiş bir tür olmalıdır, aksi takdirde kod derlenmeyecektir. Catch sonrasındaki parantez içindeki ifade bir değişken bildirimidir, böylece catch bloğu içinde istisnanın özelliklerini kullanmak veya metotlarını çağırmak için objectName değişkenini kullanabiliriz.

    12.2.9 İstisnaları Yakalamak - Örnek

    Şimdi de önceki örnekteki kodu değiştirerek içinde oluşabilecek istisnaların işlenmesini sağlayalım. Bunu yapmak içik problem yaratabilecek kodu try-catch içinde sarmalıyoruz ve sonra oluşabileceğini bildiğimiz iki tür istisnayı işlemek için birer catch bloğu ekliyoruz.



    static void ReadFile(string fileName)

    {

    // Exceptions could be thrown in the code below



    try

    {

    TextReader reader = new StreamReader(fileName);



    string line = reader.ReadLine();

    Console.WriteLine(line);

    reader.Close();

    }

    catch (FileNotFoundException fnfe)



    {

    // Exception handler for FileNotFoundException

    // We just inform the user that there is no such file

    Console.WriteLine(

    "The file '{0}' is not found.", fileName);

    }

    catch (IOException ioe)



    {

    // Exception handler for other input/output exceptions

    // We just print the stack trace on the console

    Console.WriteLine(ioe.StackTrace);

    }

    }



    Şimdi metotumuz farklı çalışıyor. new StreamReader(filename) kurucusunun çalıştırılması sırasında StreamReader başlatılırken FileNotFoundException istisnası fırlatılınca, CLR aşağıdaki satırları çalıştırmayacak ve istisnayı yakalayan kod olan catch (FileNotFoundException fnfe) satırına atlayacaktır.

    catch (FileNotFoundException fnfe)

    {

    // Exception handler for FileNotFoundException



    // We just inform the user that there is no such file

    Console.WriteLine("The file '{0}' is not found.", fileName);

    }

    Örnekte, dosyanın bulunmadığına dair bir mesaj standart çıktı üzerinde basılarak gösteriliyor.



    The file 'WrongTextFile.txt' is not found.

    Benzer şekilde, reader.ReadLine() çalıştırılması sırasında IOException istisnası fırlatılırsa, bu istisnanın işlenmesi aşağıda verilmiştir:




    catch (IOException ioe)

    {

    // Exception handler for FileNotFoundException



    // We just print the stack trace on the screen

    Console.WriteLine(ioe.StackTrace);

    }

    Bu blok, istisna yığıtının standart çıktı üzerindeki izlencesini görüntüler. İstisnanın oluştuğu satır ile catch bloğunun çalıştırıldığı yer arasında kalan hiçbir kod yürütülmez.





    Son kullanıcıya istisna ile ilgili tam bilginin verilmesi her zaman iyi bir alışkanlık olmayabilir!

    İstisna işlenmesi ile ilgili en iyi alışkanlıkları bu bölümün ilerleyen bölümlerinde tartışacağız.



    12.2.10 Yığıt İzlencesi



    Yığıt izlencesi istisnanın programda oluştuğu yer gibi, istisna hakkında ayrıntılı bilgi içerir. İstisnaya neden olan sorunu anlamaya çalıştığınızda, yığıt izlencesi programcılar için çok yararlıdır. Yığıt izlencesindeki teknik bilgiler, programcılar ve sistem yöneticileri tarafından kullanılmak üzere tasarlanmıştır, son kullanıcılar tarafından değil. Hata ayıklama sırasında yığıt izlencesi paha biçilmez bir araçtır.

    12.2.11 Yığıt İzlencesi – Örnek

    Birinci örnekte yığıt izlencesi aşağıda verilmiştir:



    Unhandled Exception: System.IO.FileNotFoundException: Could not find file '…\WrongTextFile.txt'.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

    at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)

    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)

    at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)

    at System.IO.StreamReader..ctor(String path)

    at Exceptions.Demo1.ReadFile(String fileName) in Program.cs:line 17

    at Exceptions.Demo1.Main() in Program.cs:line 11


    Sistem “WrongTextfile.txt” dosyasını bulamamıştır ve FileNotFoundException istisnası fırlatılır.


    12.2.12 Yığıt İzlencesini Okuma

    Yığıt izlencesini kullanabilmek için yapısına aşina olmalısınız. Yığıt izlencesi aşağıdaki bilgileri içerir:




    • İstisna sınıfının tam adı;

    • Hata ile ilgili bir ek bilgi mesajı;

    • Çağrı yığıtı ile ilgili bilgi;

    Yukarıdaki örnekte görülen System.IO.FileNotFoundException istisnanın tam adıdır. Hata iletisi aşağıdaki gibidir: "'…\WrongTextFile.txt' dosyası bulunamadı". Bunu takiben, çağrı yığıtının tam bir görüntüsü izler. Çağrı yığıtındaki her satır aşağıdaki dizilişe uyar:

    at .. in .cs:line

    Her metot ayrı bir satırda gösterilir. İlk satır istisnayı fırlatan metottur ve son satırda – Main() metotu bulunur (ancak istisna, programın ana iş parçacığı haricinde herhangi bir başka iş parçacığı tarafından fırlatılmışsa Main() metotu izlencede bulunmayabilir). Her metotun içerdiği sınıf ve mümkünse kaynak kod satırı hakkında tam bilgi verilir.



    at Exceptions.Demo1.ReadFile(String fileName) in …\Program.cs:line 17

    Eğer ilgili sınıf hata ayıklama bilgileri ile derlendiyse, satır numaraları da gösterilir (satır numaraları, değişken adları ve diğer teknik bilgiler de bu bilgilere dahildir). .NET derlemeleri arasında hata ayıklama bilgisi bulunmaz, ancak 'hata ayıklama sembolleri’ olarak adlandırılan (.pdb) uzantılı ayrı dosyalarda bulunur. Örnekteki yığıt izlencesinde görüldüğü gibi, hata ayıklama bilgileri bazı derlemeler için mevcutken, diğerleri (.NET derlemeleri gibi) için mevcut değildir. Yığıt izlencesinde bazı girdiler satır numarasına sahipken, diğerlerinin – sahip olmamasının nedeni budur.

    Eğer istisnayı fırlatan metot bir kurucu metotsa, yığıt izlencesinde metot adı yerine .ctor (constructor) sözcüğü geçer (System.IO.StreamReader..ctor(String path) gibi).
    Yığıt izlencesindeki bu zengin bilgi, sınıfı, metotu ve hatanın oluştuğu kaynak satırı bile hızlı ve kolay bir şekilde bulmamızı sağlar. Böylece, hataya yol açan problemi analiz etmek ve düzeltmek genellikle nispeten daha basit olur. Yığıt izlencesini desteklemeyen C ve Pascal gibi diller için bunu söyleyemeyiz.


    12.2.12 İstisnaların Fırlatılması (throw Yapısıyla)

    C# dilinde istisnaların fırlatılması için throw anahtar sözcüğü kullanılır. İstisna tanımı hata hakkında gerekli tüm bilgileri içeren bir satır koddur. İstisnayı içeren sınıf sadece bir gereksinim olarak doğrudan yada dolaylı olarak System.Exception sınıfından türetilir.


    Bir örnek aşağıda verilmiştir:

    static void Main()

    {

    Exception e = new Exception("There was a problem");



    throw e;

    }

    Program çalıştırıldığında sonucu aşağıda verilmiştir:

    Unhandled Exception: System.Exception: There was a problem

    at Exceptions.Demo1.Main() in Program.cs:line 11




    1   ...   23   24   25   26   27   28   29   30   31






        Ana sayfa


    C# İle biLGİsayar programlama temelleri (C# Programlama Kitabı) Svetlin Nakov & Co

    Indir 3.36 Mb.