Return-Try-Catch-Finally Çıkmazı - C#
Aslında yazılım dünyasının basit bir kesiti olmasına rağmen birçok kişinin sorduğu, merak ettiği, cevap bulup unutup kodlama yaparken tekrar aklına soru olarak düşen bir durumdur dönüş yapan fonksiyonlarda try-catch-finally kullanımı; return ü nereye koymalıyım ? finally nerede durmalı ? Olası bir hata durumunda akışı nasıl yönetmeliyim ?
StackOverFlow türü kaynakçalara, MSDN makalelerine ve muhtelif bilişim blog larına bakacak olursa birçok içerik bulabiliriz bu durumla ilgili.
Ben de birkaç örnek ile bu durumu ele alıp paylaşmak istedim.
Aslında bu blokların yer aldığı en ideal akış durumu bellidir, burada önemli olan olası hata durumlarda akışı nasıl yöneteceğimize ve hata durumunda fonksiyon geri dönüşünü ne olmalıdıra bir yanıtımızın olması önemlidir. Buna karar verebilmek için de dotnet framework alt yapısının hatanın oluşum durumuna göre nasıl davrandığını biliyor olmamız gerekmektedir, bu durumları birkaç örnekte simüle edip nasıl davrandığını görelim.
Kabul gören yerleşim şu şekildedir;
fonksiyonumuz
{
dönüş değişkenimize hata durumunda döneceği bir değer atanması;
try
{
işlemlerimiz ve dönüş değişkenin döneceği değerin atanması;
}
catch
{
...
}
finally
{
her türlü durumda yapacağımız işlemler;
}
return dönüş değişkenimiz;
}
NOT :
1- Return finally bloğundan önce, catch bloğundan sonra yer alamaz,
2- Finally bloğumuz yoksa bile return catch bloğundan sonra yer alamaz,
3- Eğer Finally, Catch' den sonra da bir return ifademiz yoksa try bloğu içinde yer alamaz.
4- Fakat şöyle bir kullanım da mümkündür lakin yukarıda yer verdiğim akıştan farkı yoktur.
fonksiyonumuz
{
dönüş değişkenimize hata durumunda döneceği bir değer atanması ;
try
{
return : işlemlerimiz ve dönüş değişkenin döneceği değerin atanması;
}
catch
{
...
}
finally
{
her türlü durumda yapacağımız işlemler;
}
return : hata durumunda dönecek sabit değişkenimiz;
}
Birkaç senaryo ile bir örnek üzerinden gidelim;
Aldığı iki nümerik değişken üzerinden hesaplamalar yapan bir fonksiyonumuz ve dönüşü yazdıran bir programımız olsun.
Senaryo-1 : Hatasız olağan akış
Senaryo 3 : Kasıtlı hata oluşturalım - try bloğu içerisinde dönüş değişkenini hesaplayan işlemlerimizden önce-
Senaryo 4 : İşlem anında olağan hata. Şimdi ise toplama fonksiyonumuzu bölme fonksiyonuna çevirelim ve 3 ün 0 a bölündüğü bir durumu simüle ederek olağan hata tetikleyelim.
Tahmin ettiğiniz üzere; önce hata mesajı tetikleniyor, daha sonra finally ve en son da return sabit değerimiz olan 0 dönüyor.
Son Sözler : Finally her zaman ilk işler !
Finally bloğumuz hata durumunda da normal akışta da her zaman ilk işleyecek bloktur try bloğundaki işlemlerimizden sonra. Bu yüzden hata durumunda veya normal akışta fonksiyon işini bitirdiğinde yapmasını istediğimiz tüm sonlandırıcı işlemleri burada konumlandırmamızda fayda vardır; veritabanı bağlantılarının sonlandırılması, GarbageCollector' ın çağırılması..vs gibi.
Hata durumunda veya hatasız akışta neyi nasıl döndüreceğimize karar vermemiz elzemdir, bu kurgumuzu da yukarıdaki akışa göre yönetmeliyiz.
Referanslar :
1- MSDN Makale-1
2- MSDN Makale-2
3-StackOverFlow Örnek Vaka
StackOverFlow türü kaynakçalara, MSDN makalelerine ve muhtelif bilişim blog larına bakacak olursa birçok içerik bulabiliriz bu durumla ilgili.
Ben de birkaç örnek ile bu durumu ele alıp paylaşmak istedim.
Aslında bu blokların yer aldığı en ideal akış durumu bellidir, burada önemli olan olası hata durumlarda akışı nasıl yöneteceğimize ve hata durumunda fonksiyon geri dönüşünü ne olmalıdıra bir yanıtımızın olması önemlidir. Buna karar verebilmek için de dotnet framework alt yapısının hatanın oluşum durumuna göre nasıl davrandığını biliyor olmamız gerekmektedir, bu durumları birkaç örnekte simüle edip nasıl davrandığını görelim.
Kabul gören yerleşim şu şekildedir;
fonksiyonumuz
{
dönüş değişkenimize hata durumunda döneceği bir değer atanması;
try
{
işlemlerimiz ve dönüş değişkenin döneceği değerin atanması;
}
catch
{
...
}
finally
{
her türlü durumda yapacağımız işlemler;
}
return dönüş değişkenimiz;
}
NOT :
1- Return finally bloğundan önce, catch bloğundan sonra yer alamaz,
2- Finally bloğumuz yoksa bile return catch bloğundan sonra yer alamaz,
3- Eğer Finally, Catch' den sonra da bir return ifademiz yoksa try bloğu içinde yer alamaz.
4- Fakat şöyle bir kullanım da mümkündür lakin yukarıda yer verdiğim akıştan farkı yoktur.
fonksiyonumuz
{
dönüş değişkenimize hata durumunda döneceği bir değer atanması ;
try
{
return : işlemlerimiz ve dönüş değişkenin döneceği değerin atanması;
}
catch
{
...
}
finally
{
her türlü durumda yapacağımız işlemler;
}
return : hata durumunda dönecek sabit değişkenimiz;
}
Birkaç senaryo ile bir örnek üzerinden gidelim;
Aldığı iki nümerik değişken üzerinden hesaplamalar yapan bir fonksiyonumuz ve dönüşü yazdıran bir programımız olsun.
Senaryo-1 : Hatasız olağan akış
Görüleceği üzere önce finally bloğu işler daha sonra ise return süreci gerçekleşir.
Senaryo 1 : Hatasız akış kodlaması
Senaryo 2 : Kasıtlı hata oluşturalım - try bloğu içerisinde dönüş değişkenini hesaplayan işlemlerimizden sonra-
Senaryo 2 : Kasıtlı hata tetiklediğimiz akış kodlaması -dönüş değerini hesapladığımız işlemler sonrası-
Bu senaryoda return değişkenimizi hesaplayan işlemler hatasız işliyor, değeri atıyoruz ve bir şekilde hata durumu oluşuyor, return değerini hesaplayabildiğimiz için önce hata mesajı döner daha sonra finally işlemimiz fakat return değeri hesaplandığı için dönüş değerini doğru olarak ekrana yazdırırız.
Senaryo 2 : Kasıtlı hata tetiklediğimiz akış kodlaması -dönüş değerini hesapladığımız işlemler sonrası-
Senaryo 3 : Kasıtlı hata oluşturalım - try bloğu içerisinde dönüş değişkenini hesaplayan işlemlerimizden önce-
Kasıtlı hatayı ( throw new exception; ) return değerini hesaplayan işlemlerden önce tetiklersek hata mesajının, daha sonra finally bloğunun işlediğini ve hesaplama yapma adımına kadar gelemediğimiz için return değişkenine atadığımız sabit değerin döndüğünü görürüz. Biz örneğimizde sabit dönüş değeri olarak 0 belirlemiştik.
Senaryo 3 : Kasıtlı hata oluşturalım - try bloğu içerisinde dönüş değişkenini hesaplayan işlemlerimizden önce-
Senaryo 4 : İşlem anında olağan hata.
Tahmin ettiğiniz üzere; önce hata mesajı tetikleniyor, daha sonra finally ve en son da return sabit değerimiz olan 0 dönüyor.
Son Sözler : Finally her zaman ilk işler !
Finally bloğumuz hata durumunda da normal akışta da her zaman ilk işleyecek bloktur try bloğundaki işlemlerimizden sonra. Bu yüzden hata durumunda veya normal akışta fonksiyon işini bitirdiğinde yapmasını istediğimiz tüm sonlandırıcı işlemleri burada konumlandırmamızda fayda vardır; veritabanı bağlantılarının sonlandırılması, GarbageCollector' ın çağırılması..vs gibi.
Hata durumunda veya hatasız akışta neyi nasıl döndüreceğimize karar vermemiz elzemdir, bu kurgumuzu da yukarıdaki akışa göre yönetmeliyiz.
Referanslar :
1- MSDN Makale-1
2- MSDN Makale-2
3-StackOverFlow Örnek Vaka