Makale Özeti

Bu makalemde sizlere kural dışı durumlardan bahsedeceğim. Gerçekten kolaylıkla her projenizde ve uygulamanızda kullanabileceğiniz çok önemli bir kavram. İstisnai durumlarda olayları kontrol etmenize kontrol altına almamız açısından göz ardı edilmeyecek , edilemeyecek bir konu.

Makale

Kural Dışı Durum Yönetimi


               Bu makalemde sizlere kural dışı durumlardan bahsedeceğim. Gerçekten kolaylıkla her projenizde ve uygulamanızda kullanabileceğiniz çok önemli bir kavram. İstisnai durumlarda olayları kontrol etmenize kontrol altına almamız açısından göz ardı edilmeyecek , edilemeyecek bir konu. Örneğin, Drag Drop işlemi yapıyorsunuz ve bir listbox’ınızdan diğer listbox’ınıza elemanlardan birini sürükleyip bırakacaksınız. Listbox’ımızın boş bir yerine tıkladığımızda orada bir hata oluşacaktır peki bunu nasıl yok edebiliriz ? (İlerleyen kısımlarda ve uygulamamızda bu istisnai duruma değindik) Cevap aslında çok basit işlemlerimize bir try ve catch anahtar kelimelerinden oluşan standart kullanımımızı eklediğimiz zaman bu istisnai ve olası tek hatayı kontrol altına almış bulunuyoruz. Try , catch dediğimiz zaman artık kural dışı durumlarımızın anahtar kelimelerine girmiş bulunuyoruz. Kural dışı durumlarda toplam 4 anahtar kelimemiz bulunuyor ve bunların incelikleriyle her istisnai durumu yakalayabiliyoruz.
Anahtar Kelimeler: Try, Catch, Finally, Throw .

      Try Catch kullanımın temel örneğini verecek olursak,
         
         try
                //Hata oluşan veya duruma göre oluşabilecek kod bloğu 
         }
        catch{
               //Hataların yakalandığı yer
        }

                try bloğundaki her türlü hatayı catch ifadesi kısmında yakalanacaktır. Burada her türlü hatayı yakalayabilmektedir fakat biz 2 hata çıkma olasılığı görüyoruz ve bu hata ihtimallerine göre farklı işlemler yaptırmak istersek tek catch ifadesi yetersiz kalacaktır. İki catch ifadesi kullanabilmeliyiz yine de iki ayrı durumu ele almalıyız işte burada devreye Exception sınıfı diye bir kavram giriyor ve bahsetmeden geçmek silahımızı kuşanmadan düello yapmaya benzemektedir. O zaman Exception sınıfımız ve standart türetilmiş exception’larımıza(kural dışı durum) değinelim.
C# taki her kural dışı durum Exception sınıfından türetilmektedir. Her kral dışı durum Exception sınıfının bir alt üyesidir. C# ta Exceptionlar iki kategoriye ayrılmıştır uygulama programı(ApplicationException) üzerinde oluşan istisnai durumlar ve sistem istisnai durumları(SystemException).
System uzay alanında (Namespace) tanımlı Derleyiciyle birlikte gelen Exception’ların bir kısmına göz atacak olursak:
DivideByZeroException: Sıfıra bölme hatasında oluşan exception
IndexOutOfRangeException: Dizinin sınırı dışına çıkılmıştır ( C’ deki deyimiyle dizi taşmıştır)
NullReferenceException: Null referans üzerinde işlem yapılmaktadır. Başka bir nesneyi göstermemektedir.
İsterseniz bu kullanımları bir Windows uygulaması üstünde inceleyelim ve böylece teoride kalmaz ve işlemlerimizi pratiğe dökeriz.
          Tasarımımız aşağıdaki gibi olsun:


           Visual Studio.NET imizi açıp Windows application’ı seçtikten sonra Formumuza standart gelen namespace’lere şunları da ekleyelim:
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
Bu isim alanlarımız SqlException denememiz için gerekli. Sqlserver’a bağlanmayı deneyeceğiz.
Ardından sınıfımızın içine şu alanları ekleyelim:

            public partial class Form1 : Form
           {
                   int[] iAdizi = new int[10];
                   int iTut = 0;
                   public Form1()
                   {
                         InitializeComponent();
                    }
            }
         Bu iki alan Dizi Taşması örneğimiz için eklenmiştir.
         DivideByZero denemesi isimli groupbox’ımızdaki butona çift tıklayalım ve şu kodları yazalım sırasıyla studio.NET le standart gelen isimleri kullandık.

Kodlarımız:

            int iSayi1,iSayi2;
            try 
            {
                         iSayi1 = Convert.ToInt32(textBox1.Text);
                         iSayi2 = Convert.ToInt32(textBox2.Text); 
                         iSayi1 /= iSayi2;
                          MessageBox.Show("Herhangi Bir Hata Meydana Gelmedi ve Buraya Kadar Geldi Sonuç= " + iSayi1); 
             } 
            catch (DivideByZeroException)
           {
                         MessageBox.Show("Sıfıra bölme hatası Catch'e Düştü");
            }
           catch
           {
                         MessageBox.Show("İkinci catch: herhangi bir hata meydana geldi");
            }

                 Bu deneme amaçlı ve istediğiniz herşeyi deneyebilirsiniz bölüme sıfır girdiğinizde DivideByZeroException’a düşecektir. Diğer hata durumlarında ikinci catch’e yakalanacaktır. Tabiki de burada ardıardına iki catch kullandığımızı unutmamalıyız ikinci catch bütün hataları yakalamaktadır eüer ilk catch’den önce ikincisini yazsaydık yani DivideByZeroException lı catch’imizi ikinci catch olarak ele alsaydık oraya asla düşmezdi çünkü her hatayı yakalayan catch { } ifademiz hatayı yakalayıp çıkacaktı. Fakat DivideByZeroException kontrolümüz gerçekleşemeyecekti.
Dizi Taşması örneği adlı groupbox’ımızdaki butona tıklayıp şu kodları yazalım:

            try
           {
                           iAdizi[iTut] = Convert.ToInt32(textBox3.Text); 
                           iTut++;
                           listBox1.Items.Add("" + iTut + " indise " + iAdizi[iTut-1] + " Eklendi"); 
            }
           catch (IndexOutOfRangeException)
           {
                           MessageBox.Show("Dizinin indeksini aştın 10 elemandan fazla Girdin ve catch'e yakalandım aslıdna istediğimizde buydu");
                           listBox1.Items.Add("Hata"); 
           } 
           catch
         {
                          MessageBox.Show("Diğer hata meydana geldi Sadece Sayı girmeliydin bu gerçekten beklenmedik bir hata");
                          listBox1.Items.Add("Diğer bir Hata");
         }

          Gördüğünüz gibi dizimizin sınırları dışına çıkarsak IndexOutOfRangeException tarafından bu hata yakalanmaktadır. Burada her tıkladığımızda ilk indisten başlayarak dizimize bizim girdiğimiz rakamları yerleştirmektedir. Dizimizi ve iTut alanımızı sınıfımızın başında tanımlamıştık. Diğer hatalar mesela textboxın boş bırakılması veya karakter girilmesi durumunda ikinci genel catchimiz tarafından yakalanacaktır.

Üçüncü olarak throw groupboxımızın butonuna çift tıklayıp şu kodlarıda yazalım (Fırlat butonu) :
    try
    {
        kuraldisi();
    }
    catch
    {
        MessageBox.Show("İkinci Kez Yakalandı");
    }
            Örneğimizi ve throw’u anlamak için de kuraldisi adında bir metot yazmamız gerekli.
kuraldisi() metodumuz:
    private void kuraldisi()
    {
        try
        {
                MessageBox.Show("Kural Dışı Durum Fırlatılıyor");
               throw new IndexOutOfRangeException();
       }
        catch
        {
               MessageBox.Show("İstisnai Durum Yakalandı");
               throw;
        }
    }
          Fırlat butonumuza tıkladığımızda try bloğumuzuun içindeki kuraldisi(); metodumuz çalıaşcaktır ardından kuraldisi metodumuzda yeni bir exception new lenmekte yani oluşturulmaktadır. Ardından catch ifademize düşmekte ve oluşturduğumuz IndexOutOfRangeException istisnai durumumuz tekrar fırlatılmaktadır ve metodumuzun işleyişi bittiği için butonumuzun Click event’ında kod işleyişi yoluna devam etmektedir. Tekrar “throw;” anahtar kelimesi ile fırlattığımız istisnai durum bu sefer ikinci kez catch’e yakalanacaktır.

          Checked Uncheck denemesi adlı dene adlı butonuzumuzun click event’inede şunları yazalım:
int iCSayi1=2000000000,iCSayi2=2000000000;
int iSonuc;
if (radioButton1.Checked == true)
{
    try
    {
        checked
        {
        iSonuc = checked((int)(iCSayi1 * iCSayi2));
        }
    }
    catch (OverflowException)
    {
        MessageBox.Show("OverflowException meydana geldi");
    }
}
else
{
    try
    {
        unchecked
        {
        iSonuc = unchecked((int)(iCSayi1 * iCSayi2));
       MessageBox.Show("OverflowException a Düşmedi");
    }
    }
    catch (OverflowException)
    {
    MessageBox.Show("Buraya Düşmeyecek");
    }
}
            Bu örneğimizde eğer radiobutton1’i seçtiğimiz zaman check özelliği eklenerek çalışılmış, radiobuton2 yi seçersek ise uncheckd özelliği ile çalışılmış. Nedir bu checked ve unchecked ? Açıklayacak olursak her dilde her değişkenin belli bir sayı tutma kapasitesi var atıyorum C dilinde integer(tam sayılar) veri tipimiz 2 byte yer kaplıyor ve 32000 i geçemiyor diyelim eğer ikinci değilkenimiz de 32000 olur ve çarpma işlemine tabi tutulursa hesap makinelerinde gördüğüüz kapasite farklılıklarında çık 32323e+2 gibi yazılar yani overflow meydana gelir bunlar artimetik işlemlerde meydana gelme olasılığı olan durumlardır ve bir çok hataya sebebiyet verir. İşte checked özelliği bu kontrolü sağlamamızı unchecked ise gözardı etmemizi sağlar. Checked ve uncheck anahtar kelimelirimiz bu gibi durumlarda büyük bir kurtarıcı rolü oyanamaktadır. Genel kullanımını taslak olarak yazacak olursak:
          try{
                    checked{
                          //Meydana gelecek overflow lara sahip aritmetik işlem
                     } 
          }
         catch(OverflowException)
         {
                      //Overflow durumunda vereceğimiz mesaj 
          }
             Not: Aritmerik işlemimizin önüne yukarıda gördüğünüz gibi checkd veya unchecked ardından da veri tipini yazmamız gereklidir.
                SqlException istisnai durumunu ve database işlemlerinde meydana gelebilecek durumlar içinde SqlException istisnai durumunu kullanabiliriz. Butonumuzun click evventına yine şunları yazalım ( Bu cümleyi çok kullandığımın farkındayım ama hep click eventına yazmak zorundayız ne yapalım )

Kod:
        string con = "Data Source=(local);Initial Catalog=benneredeyim;Integrated Security=True"
        SqlCommand InsertCurrencyCommand = new SqlCommand();
        SqlConnection conn = new SqlConnection(con);
        InsertCurrencyCommand.CommandText =
        "INSERT tablom(deger)" +
        " VALUES('selamlar')";

       InsertCurrencyCommand.Connection = conn;
       try
      {
                  conn.Open();
                  InsertCurrencyCommand.ExecuteNonQuery();
                  MessageBox.Show("Hata Olmadı Burayı Görmen biraz Zor :)");
       } 
       catch (SqlException hata)
      {
                  MessageBox.Show(hata.Message.ToString());
                  MessageBox.Show(" >Hata< !");
      }
       finally
      {
                   conn.Close();

       }

                 Diğer database connectionları SqlCommand üzerinde fazla durmayacağım burada şunu bilmeniz yeterli, büyük ihtimalle sizin Sql Server’ınızda benneredeyim isimli bir database olmadığı ve bir ihtimal olsa bile, içinde tablom isimli ve deger adlı kolona sahip bir tablo olamdığı için hata meydana gelecektir. Buradaki her türlü hatayı SqlException ile yakalayabiliriz. Mesaj kutumuzun içinde hata.Message.ToString() yapmamızın nedeni ise gelen hatayı MessageBox içinde yazdırmak içindir en azından karşınıza Continu veya Quit gibi programın büyük bir hataya sebebiyet verdiği gibi kaba bir kutucuk yerine güzel bir messagebox ile bu işi çözümleyebiliriz. Finally anahtar kelimesindende söz etmek gerekirse hata çıksada çıkmasada o kod bloğu işleyecektir sanırım kolay ama etkileyici bir özelliğe sahip.
                  Uygulamamızdaki son örneğimiz ise sürükle bırak işlemleri ile ilgili iki listbox arasında veya bir listbox’dan herhangi bir yere sürükle bırak yaparken başıma gelen ve beni çıldırtan listbox’ın boş bir yerine tıkladığımızda meydana gelen bir hata bunuda kolayca try-catch bloğuyla bertaraf edebiliriz.

Sürükle bırak örneğimiz için hazırlanmış olan kodlarımız:
         private void listBox2_MouseDown(object sender, MouseEventArgs e)
        {
                   try 
                   {
                            Point pTut = new Point(e.X, e.Y);
                             int iIndeksNo = listBox2.IndexFromPoint(pTut);
                              if (e.Button == MouseButtons.Left)
                              {
                                  listBox2.DoDragDrop(listBox2.Items[iIndeksNo].ToString(), DragDropEffects.All);
                               }
                    }
                   catch
                  {  
                           MessageBox.Show("Lütfen Boş Bir Yere Tıklamayınız"); 
                  }
       } 

       private void listBox3_DragOver(object sender, DragEventArgs e)
      {
                     if (e.KeyState == 1)
                    {
                                     e.Effect = DragDropEffects.Copy;
                     }
      }

      private void listBox3_DragDrop(object sender, DragEventArgs e)
     {
                   listBox3.Items.Add(e.Data.GetData(DataFormats.Text).ToString());
      }

          Yukarıdada belirtilen her event a altında yazan kodlarımızı yazalım ve örneğimizi tamamlayalım. Sürükleme işlemi mouse’un sol tuşuna basmamızla gerçekleşecektir. Boş bir yere tıkladığımızda ise artık messagebox’ımızla belirttiğimiz uyarıyı kendimiz verebileceğiz isterseniz orayı boş bırakıp hiç bir şey olmamış gibi yolunuza devam edebilirsiniz.
Böylece makalemizde kural dışı durumları ve onları yönetmeyi irdelemiş olduk. Eğer makale hakkında soru, görüş veya önerileriniz olursa inhoftec@gmail.com adresine mail atabilirsiniz elimden geldiğince cevaplamaya çalışacağım. Programın çalışan versiyonunu ise BURADAN indirebilirsiniz.
Yazan: Volkan Atasever