Try / catch / throw ve try / catch (e) / throw e arasındaki fark


103

Arasındaki fark nedir

try { }
catch
{ throw; }

ve

try { }
catch(Exception e)
{ throw e;}

?

Ve ne zaman birini veya diğerini kullanmalıyım?

Yanıtlar:


151

Yapılar

try { ... }
catch () { ... } /* You can even omit the () here */

try { ... }
catch (Exception e) { ... }

her ikisi de trybloğun içine atılan her istisnayı yakalayacağı için benzerdir (ve istisnaları günlüğe kaydetmek için bunu kullanmıyorsanız, kaçınılmalıdır ). Şimdi şunlara bakın:

try { ... }
catch ()
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw;
}

try { ... }
catch (Exception e)
{
    /* ... */
    throw e;
}

Birinci ve ikinci try-catch blokları TAMAMEN aynı şeydir, sadece mevcut istisnayı yeniden atarlar ve bu istisna "kaynağını" ve yığın izini koruyacaktır.

Üçüncü try-catch bloğu farklıdır. İstisnayı attığında, kaynağı ve yığın izini değiştirecek, böylece istisnanın bu metottan, throw eo try-catch bloğunu içeren metottaki satırdan atılmış gibi görünecektir .

Hangisini kullanmalısınız? Gerçekten her duruma göre değişir.

Diyelim ki, onu bir veritabanında saklayacak Personbir .Save()yönteme sahip bir sınıfınız var . Diyelim ki uygulamanız Person.Save()yöntemi bir yerde çalıştırıyor . DB'niz Kişiyi kurtarmayı reddederse, .Save()bir istisna atar. Kullanmak mı throwyoksa throw ebu durumda? Duruma göre değişir.

Yapmayı tercih ettiğim şey:

try {
    /* ... */
    person.Save();
}
catch(DBException e) {
    throw new InvalidPersonException(
       "The person has an invalid state and could not be saved!",
       e);
}

Bu, DBException'ı yeni atılan istisnanın "İç İstisna" olarak koymalıdır. Bu nedenle, bu InvalidPersonException'ı incelediğinizde, yığın izleme, Save yöntemine kadar bilgi içerecektir (bu, sorunu çözmeniz için yeterli olabilir), ancak ihtiyacınız olursa orijinal özel duruma yine de erişebilirsiniz.

Son bir açıklama olarak, bir istisna beklediğinizde , genel olarak değil, belirli bir istisnayı gerçekten yakalamanız gerekir Exception, yani, bir InvalidPersonException bekliyorsanız, tercih etmelisiniz:

try { ... }
catch (InvalidPersonException e) { ... }

-e

try { ... }
catch (Exception e) { ... }

İyi şanslar!


34

Birincisi yığın izini korurken, ikincisi onu sıfırlar. Bu, ikinci yaklaşımı kullanırsanız, istisnanın yığın izlemesinin her zaman bu yöntemden başlayacağı ve istisna günlüklerini okuyan biri için istisnanın orijinal nedenini asla bulamayacağı için felaket olabilecek orijinal istisna izini kaybedeceğiniz anlamına gelir. .

İkinci yaklaşım, yığın izlemesine ek bilgi eklemek istediğinizde yararlı olabilir, ancak şu şekilde kullanılır:

try
{
    // do something
}
catch (Exception ex)
{
    throw new Exception("Additional information...", ex);
}

Farklılıkları tartışan bir blog yazısı var .


Bu bilmek harika bir şey!
Myles

öyleyse neden ikinciyi kullanalım? sadece ilkini kullanmak daha mı iyi?
Karim

1
İkincisi, belirli istisnaları kontrol etmeniz gerektiğinde - OutOfRangeException akla gelir - veya mesajı günlüğe kaydetmeniz gerektiğinde işe yarar. İlki {} catch (...) {} 'ye benzer bir joker karakter istisna işleyicisi gibi görünüyor. c ++ 'da.
3Kasım

1
David, bu sadece yakalama (İstisna e) kısmı için geçerli. Ve bu ayrıdır throwvs throw e.
Henk Holterman

6

Kullanmalısın

try { }
catch(Exception e)
{ throw }

yeniden atmadan önce istisna ile bir şey yapmak istiyorsanız (örneğin günlüğe kaydetme). Yalnız atış, yığın izini korur.


ve buradaki "atışı" bir "e atışı" ile değiştirirsem ne olur?
Karim

5

Parametresiz catch ile a arasındaki fark catch(Exception e), istisnaya bir referans almanızdır. Çerçeve sürüm 2'den yönetilmeyen istisnalar, yönetilen bir istisnaya sarılır, bu nedenle parametresiz istisna artık hiçbir şey için yararlı değildir.

Arasındaki fark throw;ve throw e;ilki istisnalar rethrow için kullanılır ve ikinci bir yeni oluşturulan özel durum için kullanılır olmasıdır. İkincisini bir istisnayı yeniden atmak için kullanırsanız, buna yeni bir istisna gibi davranacak ve tüm yığın bilgilerini orijinal olarak atıldığı yerden değiştirecektir.

Bu nedenle, söz konusu alternatiflerden hiçbirini kullanmamalısınız. Parametresiz yakalama kullanmamalısınız throw;ve bir istisnayı yeniden atmak için kullanmalısınız .

Ayrıca, çoğu durumda, tüm istisnalar için temel sınıftan daha spesifik bir istisna sınıfı kullanmalısınız. Yalnızca beklediğiniz istisnaları yakalamalısınız.

try {
   ...
} catch (IOException e) {
   ...
   throw;
}

İstisnayı yeniden atarken herhangi bir bilgi eklemek isterseniz, tüm bilgileri korumak için bir iç istisna olarak orijinal istisna ile yeni bir istisna oluşturursunuz:

try {
   ...
} catch (IOException e) {
   ...
   throw new ApplicationException("Some informative error message", e);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.