Neden yakalamak ve C # bir istisna yeniden?


557

Ben seri hale getirilebilir DTOs Veri Transferi Nesne C # makalesine bakıyorum .

Makale bu kod parçasını içerir:

public static string SerializeDTO(DTO dto) {
    try {
        XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
        StringWriter sWriter = new StringWriter();
        xmlSer.Serialize(sWriter, dto);
        return sWriter.ToString();
    }
    catch(Exception ex) {
        throw ex;
    }
}

Makalenin geri kalanı aklı başında ve mantıklı görünüyor (ama bir noob'a), bu try-catch-throw bir WtfException oluşturur ... Bu, istisnaları hiç ele almamakla tamamen eşdeğer değil mi?

Ergo:

public static string SerializeDTO(DTO dto) {
    XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
    StringWriter sWriter = new StringWriter();
    xmlSer.Serialize(sWriter, dto);
    return sWriter.ToString();
}

Yoksa C # hata işleme hakkında temel bir şey eksik mi? Java (eksi işaretli istisnalar) ile hemen hemen aynı, değil mi? ... Yani, ikisi de C ++ 'ı rafine etti.

Yığın Taşması sorusu Parametresiz yakalamayı yeniden atmak ve hiçbir şey yapmamak arasındaki fark nedir? denemek-yakalamak-at-bir-op olduğunu benim görüş destekliyor gibi görünüyor.


DÜZENLE:

Gelecekte bu konuyu bulan herkes için özetlemek gerekirse ...

YAPMA

try {
    // Do stuff that might throw an exception
}
catch (Exception e) {
    throw e; // This destroys the strack trace information!
}

Yığın izleme bilgisi, sorunun temel nedenini belirlemek için çok önemli olabilir!

YAPMAK

try {
    // Do stuff that might throw an exception
}
catch (SqlException e) {
    // Log it
    if (e.ErrorCode != NO_ROW_ERROR) { // filter out NoDataFound.
        // Do special cleanup, like maybe closing the "dirty" database connection.
        throw; // This preserves the stack trace
    }
}
catch (IOException e) {
    // Log it
    throw;
}
catch (Exception e) {
    // Log it
    throw new DAOException("Excrement occurred", e); // wrapped & chained exceptions (just like java).
}
finally {
    // Normal clean goes here (like closing open files).
}

Daha az özel olanlardan önce (tıpkı Java gibi) daha özel istisnaları yakalayın.


Referanslar:


8
İyi özet; sonunda blok dahil etmek için ekstra puan.
Fredrik Mörk

i "atmak" kullanabilirsiniz eklemek istiyorum; e.Data koleksiyonundaki yönteme "throw" dan önce gönderilen parametreleri ekleyerek daha da yardımcı olabilir; bildirimi
Michael Bahig

@MickTheWarMachineDesigner (ve yarı zamanlı ressam). Ha? Microshite Suckwell (muhtemelen bildiğim kadarıyla 2005'ten itibaren) istisnalarını ele almaktan bahsediyorsunuz. Genel olarak istisna yönetimi hakkında konuşuyordum. Ve evet, DÖRDÜNCÜ DÖRT YIL ÖNCE yayınladığımdan beri biraz öğrendim .... Ama evet, geçerli bir noktanız olduğunu itiraf ediyorum, ama gerçek noktayı kaçırdığınızı düşünüyoruz; benim sapmamı alırsan? Bu soru C # GENELLEŞTİRİLMİŞ özel durum işleme hakkında; ve daha ayrıntılı olarak ... TÜM türlerin istisnalarını yeniden düzenleme hakkında. Güzel?
corlettk

Lütfen sorunuzdaki düzenleme özeti bölümünü kendi yanıtına taşımayı düşünün. Neden Görmekten için söz konusu bile kendini yanıtı değiştirmek ve söz konusu gömülü Yanıt .
DavidRR

2
"Dışkı meydana geldi" bölümünü kimse fark etmedi mi? kod kaka için gitti gibi geliyor!
Jason Loki Smith

Yanıtlar:


430

İlk; makaledeki kodun yaptığı şey kötülüktür. throw existisnadaki çağrı yığınını bu throw ifadesinin olduğu noktaya sıfırlar; istisnanın gerçekte nerede yaratıldığı hakkında bilgi kaybetmek.

İkincisi, sadece yakalamak ve bu şekilde yeniden atmak, ben katma değer görmüyorum, yukarıdaki kod örneği throw extry-catch olmadan sadece iyi (veya biraz daha iyi verilen) olurdu .

Ancak, bir istisna yakalamak ve yeniden düşünmek isteyebileceğiniz durumlar vardır. Günlüğe kaydetme bunlardan biri olabilir:

try 
{
    // code that may throw exceptions    
}
catch(Exception ex) 
{
    // add error logging here
    throw;
}

6
@Fredrick, sadece fyi (muhtemelen biliyor olsanız da) ex, o nesneyi kullanmayacaksanız , o zaman onu başlatmaya gerek yoktur.
Eoin Campbell

78
@Eoin: Eğer somutlaştırılmamışsa günlüğe kaydetmek oldukça zor olurdu.
Sam Axe

30
Evet, bence "kötülük" hemen hemen doğru ... büyük bir kod gövdesinden bir yere atılan boş gösterici istisnası durumunu düşünün. Mesaj vanilya, yığın iz bırakmadan "bir yerde bir şey boştu" kaldı. Üretim öldüğünde iyi DEĞİL; ve alevli problemi çözmek için dakika veya daha az zamanınız yok ve bunu reddedin veya düzeltin ... İyi istisna yönetimi, altın ağırlığına değer.
corlettk

4
Java için de bu doğru mu? "Atmak" mı, "eski atmak" mı?
23'te JasonStoltz

8
@ Jason, bu soruya bak . Java'da, throw exyığın izlemeyi yeniden başlatmaz.
Matthew Flaschen

117

Bunu yapma,

try 
{
...
}
catch(Exception ex)
{
   throw ex;
}

Yığın izleme bilgilerini kaybedeceksiniz ...

Ya öyle,

try { ... }
catch { throw; }

VEYA

try { ... }
catch (Exception ex)
{
    throw new Exception("My Custom Error Message", ex);
}

Yeniden incelemek isteyebileceğiniz nedenlerden biri, farklı istisnalar ele alıyorsanız, örneğin

try
{
   ...
}
catch(SQLException sex)
{
   //Do Custom Logging 
   //Don't throw exception - swallow it here
}
catch(OtherException oex)
{
   //Do something else
   throw new WrappedException("Other Exception occured");
}
catch
{
   System.Diagnostics.Debug.WriteLine("Eeep! an error, not to worry, will be handled higher up the call stack");
   throw; //Chuck everything else back up the stack
}

7
Neden sadece catch {throw} 'ı dışarıda bırakmıyorsunuz?
AnthonyWJones

3
catch {throw; }, belirli bir istisna türü listesinin en altında, yazarın durumu dikkate aldığını kanıtlamasına rağmen, bir yorum da aynı derecede yeterli olabilir. Kodu okurken tahmin etmemek iyi bir şeydir.
annakata

87
Herhangi bir nedenle, SQLException adı beni rahatsız ediyor.
Michael Myers

13
Bu catch (Exception) {new new Exception (...)}, istisna bilgisini gizlemediğiniz ve istisna filtrelemesini gereksiz yere zorladığınız için asla, asla, hiç yapmamanız gereken bir şeydir . Bir istisna türünü yakalayıp diğerini atmanız gereken tek zaman, bir soyutlama katmanı uyguladığınızda ve sağlayıcıya özgü bir istisna türünü (örn. XmlException'a karşı SqlException) daha genel bir katmana (örn. DataLoadingException) dönüştürmeniz gerektiğidir.
jammycakes

3
@dark_perfect yöntemin başında bu bağımsız değişkeni önceden kontrol etmeli ve ArgumentNullException'ı oraya atamalısınız (hızlı başarısız).
Andrei Bozantan

56

C # (C # 6'dan önce), VB'nin yaptığı CIL "filtrelenmiş istisnaları" desteklemez, bu nedenle C # 1-5'te bir istisnayı yeniden atmanın bir nedeni, catch () sırasında yeterli bilgiye sahip olmamanızdır. istisnayı gerçekten yakalamak isteyip istemediğinizi belirlemek için.

Örneğin, VB'de şunları yapabilirsiniz:

Try
 ..
Catch Ex As MyException When Ex.ErrorCode = 123
 .. 
End Try

... farklı MyCoceptions değerlerini farklı ErrorCode değerleriyle işlemez. V6'dan önceki C # 'da, ErrorCode 123 değilse MyException'ı yakalamanız ve yeniden atmanız gerekir:

try 
{
   ...
}
catch(MyException ex)
{
    if (ex.ErrorCode != 123) throw;
    ...
}

C # 6.0'dan beri tıpkı VB'de olduğu gibi filtreleyebilirsiniz :

try 
{
  // Do stuff
} 
catch (Exception e) when (e.ErrorCode == 123456) // filter
{
  // Handle, other exceptions will be left alone and bubble up
}

2
Dave, ama (en azından java'da) "genel" bir MyException oluşturmazsınız, bir SPECIFIC istisna türü tanımlar ve atarsınız, yakalama bloğunda türe göre farklılaştırılmasına izin verirsiniz ... Ama evet , eğer istisnanın mimarı değilseniz (JDBC'nin SQLException (yine Java) olduğunu düşünüyorum, bu iğrenç bir şekilde geneldir ve getErrorCode () yöntemini ortaya çıkarır ... Hmmm ... Bir noktanız var, sadece bu Bence bunu yapabilmenin daha iyi bir yolu var, şerefe arkadaşım, zaman ayırdığınız için çok teşekkür ederim Keith.
corlettk

1
Peki, soru "Neden C # İstisna yakalamak ve yeniden?", Ve bu bir cevap. =] ... ve özel istisnalar dışında bile, İstisna Filtreleri mantıklıdır: diyelim ki, her ikisi de SqlException olan bir SqlTimeoutException ve SqlConnectionResetException durumlarını ele alın. İstisna Filtreleri bir SqlException'ı yalnızca bu ikisinden biri olduğunda yakalamanızı sağlar, bu nedenle denemenizi / yakalamanızı bu ikisi için özdeş işlemeyle karıştırmak yerine, "ex SqlTimeoutException veya ex SqlConnectionResetException olduğunda SqlException ex'i yakalayabilirsiniz". (Ben Dave btw değilim)
bzlm

3
Filtrelenmiş istisnalar C # 6'da geliyor!
Sir Crispalot

14

Benim gibi kod sahip olmanın ana nedeni:

try
{
    //Some code
}
catch (Exception e)
{
    throw;
}

böylece bir istisna nesnesi olan catch bir kesme noktası olabilir. Bunu geliştirme / hata ayıklama sırasında çok yapıyorum. Tabii ki, derleyici tüm kullanılmayan e'ler hakkında bana bir uyarı veriyor ve ideal olarak bir sürüm derlemesinden önce çıkarılmaları gerekiyor.

Yine de hata ayıklama sırasında güzel.


1
Evet, bunu ödeyeceğim, ama evet, yayınlanan kodda görmek istemezsiniz ... ergo: Bunu yayınlamaktan
utanacağım

25
Aslında, bu gerekli değildir - Visual Studio'da bir istisna atıldığında hata ayıklayıcıyı ayarlayabilirsiniz ve sizin için bir denetçi penceresinde istisna ayrıntılarını getirir.
jammycakes

8
Hata ayıklama sırasında YALNIZCA bazı kodlar kullanmak isterseniz, # if DEBUG ... #endif kullanın ve bu satırları kaldırmanız gerekmez
Michael Freidgeim

1
Bunu birkaç kez yaptım. Arada sırada kişi serbest bırakılacak. @jammycakes Visual Studio'nun istisnadaki kırılmayla ilgili sorun, bazen istediğim istisna atılan tek (hatta türünün sadece biri) değildir. "İstisna ile atlanırsa kırılma" ile bir kırılma noktası koşulu hala bilmiyorum. O zamana kadar bu yararlı olmaya devam edecek. Michael Freidgeim: #if DEBUGİKİ etrafında try {ve } catch () {...}biraz dağınık ve açıkçası, beni rahatsız ediyor ... Ön işlemci, genel olarak, arkadaşım değil.

11

İstisnaları yeniden düzenlemenin geçerli bir nedeni, istisnaya bilgi eklemek veya belki de orijinal istisnayı kendi yaptığınız birinden sarmak olabilir:

public static string SerializeDTO(DTO dto) {
  try {
      XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
      StringWriter sWriter = new StringWriter();
      xmlSer.Serialize(sWriter, dto);
      return sWriter.ToString();
  }
  catch(Exception ex) {
    string message = 
      String.Format("Something went wrong serializing DTO {0}", DTO);
    throw new MyLibraryException(message, ex);
  }
}

Thanx, evet istisna sarma (özellikle zincirleme) mükemmel aklı başında ... aklı başında olmayan şey, sadece yığın iz chuck uzakta, ya da daha kötüsü, yemek bir istisna yakalamak olduğunu.
corlettk

10

Bu, istisnaları hiç ele almamakla tam olarak eşdeğer değil mi?

Tam olarak değil, aynı değil. Kural dışı durumun yığın izlemesini sıfırlar. Bu muhtemelen bir hata olduğunu ve bu nedenle kötü kod örneği olduğunu kabul ediyorum.


8

Eski atmak istemezsiniz, çünkü bu çağrı yığınını kaybeder. Bkz. Özel Durum İşleme (MSDN).

Ve evet, try ... catch yararlı bir şey yapmıyor (bazı nedenlerden dolayı bu bilgiyi ifşa etmek istemediğiniz sürece, çağrı yığınını kaybetmek dışında - aslında daha da kötüsü).


Throw ex komutunu kullandığınızda tüm çağrı yığınını kaybetmezsiniz, çağrı yığınının istisnanın çağrı yığınının yukarısında gerçekleştiği noktadan yalnızca bölümünü kaybedersiniz. Ancak, çağrı yığınını, istisnayı istemcinin çağırdığı yere atanan yöntemden tutarsınız. Aslında bunu kullanacağınız durumlar olabilir, yoksa Microsoft'taki iyi insanlar buna izin vermezdi. Dedi ki, ben kullanmadım. Hatırlanması gereken bir diğer konu, istisnaları atmanın pahalı olduğudur. Sadece haklı bir sebeple yapın. Günlüğe kaydetmenin haklı olacağını düşünürdüm
Charles Owen

5

İnsanlar bahsedilmeyen olduğunu bir nokta NET dilleri gerçekten uygun bir ayrım, tek gerekip gerekmediği sorusunu yapmazlar ise olmasıdır eylemde bir özel durum oluştuğunda ve bir edip çözmek o, aslında farklı sorulardır. Birinin çözülme umudu olmayan istisnalara dayalı olarak harekete geçmesi gereken birçok durum vardır ve bir istisnayı "çözmek" için gereken her şeyin yığını belirli bir noktaya çözmek olduğu durumlar vardır - başka bir işlem gerekmez .

Kişinin yalnızca "işleyebileceği" şeyleri "yakalaması" gerektiğine dair ortak bilgelik nedeniyle, istisnalar meydana geldiğinde harekete geçmesi gereken bir sürü kod yoktur. Örneğin, çok sayıda kod bir kilit alır, korunan nesneyi değişmezlerini ihlal eden bir duruma "geçici olarak" koyar, sonra nesneyi meşru bir duruma sokar ve daha sonra herkes nesneyi görmeden önce kilidi serbest bırakır. Nesne tehlikeli olarak geçersiz bir durumdayken bir istisna oluşursa, yaygın uygulama, nesneyi hala bu durumdayken kilidi serbest bırakmaktır. Çok daha iyi bir desen, nesne "tehlikeli" bir durumdayken ortaya çıkan bir istisnaya sahip olmak, kilidi açıkça geçersiz kılar, böylece ileride elde etmek için yapılacak herhangi bir girişim hemen başarısız olur.

Çoğu .NET dilinde, kodun bir istisnayı temel alarak işlem yapmasının tek yolu catchona (istisnayı çözmeyeceğini bilse bile), söz konusu eylemi gerçekleştirin ve sonra yeniden yapmaktır throw. Kod, hangi istisnanın atıldığını umursamıyorsa, başka bir olası yaklaşım, bloklu bir okbayrak kullanmaktır try/finally; ayarlamak okiçin bayrak falsebloğundan önce ve hiç trueblok çıkmadan önce ve herhangi önce returnblok içerisindeki olduğunu. Ardından, içinde ayarlanmadıysa, bir istisna oluşması gerektiğini finallyvarsayın ok. Böyle bir yaklaşım anlamsal olarak a catch/ ' dan daha iyidir throw, ancak çirkindir ve olması gerekenden daha az bakım yapılabilir.


5

Bu, bir kütüphane veya dll için programlama işlevleriniz olduğunda yararlı olabilir.

Bu rethrow yapısı, çağrı yığınını amaca uygun olarak sıfırlamak için kullanılabilir, böylece fonksiyonun içindeki tek bir fonksiyondan atılan istisnayı görmek yerine fonksiyonun kendisinden istisna elde edersiniz.

Bence bu sadece atılan istisnalar daha temiz ve kütüphanenin "köklerine" gitmez.


3

Yakalama-atmanın olası bir nedeni, yığının derinlemesine filtrelenmesini sağlayan istisna filtreleri devre dışı bırakmaktır ( rastgele eski bağlantı ). Tabii ki, eğer niyet buysa, orada bir yorum olurdu.


Bağlantıyı okuyana kadar neyi nereden bulamadım ... ve hala ne hakkında olduğunuzu tam olarak bilmiyorum ... VB.NET'e tamamen aşina olmam. Sanırım toplam "tutarsız" bildirilmesi ile sonuçlanır, değil mi? Ben statik yöntemlerin BÜYÜK bir hayranıyım .. Basit olmasının yanı sıra, özniteliklerin ayarını koddan ayırırsanız tutarsızlık şansı daha az gerçek işi yapar. Yığın "kendi kendini temizler".
corlettk

3
İnsanlar "{{Foo ();} nihayetinde {Bar ();}" 'yu ​​yazdıklarında Foo ve Bar arasında hiçbir şeyin çalışmadığını bekliyorlar. Ama bu doğru değil; Arayanız bir istisna filtresi eklediyse ve araya giren bir 'yakalama' yoksa ve Foo () atarsa, sonunda (Bar) çalışmadan önce arayandan başka bir rastgele kod çalışacaktır. Değişmezleri veya güvenliği artırdıysanız, nihayetinde 'hemen' normale döndürüleceğini ve geçici olarak başka bir kod görmeyeceğini umduğunuzda bu çok kötü.
Brian

3

Bu, catch bloğunda ne yaptığınıza ve hatayı arama koduna iletmek isteyip istemediğinize bağlıdır.

Catch io.FileNotFoundExeption exAlternatif bir dosya yolu veya benzeri bir şey söyleyebilir ve kullanabilirsiniz, ancak yine de hatayı atın.

Ayrıca Throwyerine Throw Extam yığın izini tutmak için izin verir. Ex atmak atma ifadesinden yığın izlemeyi yeniden başlatır (umarım bu mantıklıdır).


3

Diğer cevapların birçoğu, neden bir istisnayı yeniden yakalamak isteyebileceğinize dair iyi örnekler sunsa da, hiç kimse 'nihayet' bir senaryodan bahsetmemiş gibi görünüyor.

Bunun bir örneği, imleci ayarladığınız (örneğin bir bekleme imlecine) bir yönteminizin olduğu, yöntemin birkaç çıkış noktası (örn. () Return;) olduğu ve imlecin yöntemin sonu.

Bunu yapmak için tüm kodu bir try / catch / nihayetinde sarabilirsiniz. Sonunda imleci sağ imlece geri ayarlayın. Geçerli herhangi bir istisnayı gömmemeniz için, yakalamada yeniden düşünün.

try
{
    Cursor.Current = Cursors.WaitCursor;
    // Test something
    if (testResult) return;
    // Do something else
}
catch
{
    throw;
}
finally
{
     Cursor.Current = Cursors.Default;
}

1
Tarihsel olarak catchzorunlu bir parçası mıydı try...finally, yoksa bu örnekte işlevsel bir rol oynuyor mu? - Sadece iki kez kontrol ettim ve try {} finally {}yakalama bloğu olmadan da kullanabiliyorum .
Sebi

2

Gönderdiğiniz koddaki örnekte, aslında, yakalama üzerinde hiçbir şey yapılmadığı için istisnayı yakalamanın bir anlamı yoktur, sadece yeniden çözülür, aslında çağrı yığını kaybolduğundan daha iyi zarar verir .

Bununla birlikte, bir istisna durumunda başa çıkmak için arama koduna geri atmak için bazı mantık (örneğin, dosya kilidinin sql bağlantısını kapatmak veya sadece bazı günlük kaydı) yapmak için bir istisna yakalarsınız. Bu, bir iş katmanında ön uç kodundan daha yaygın olacaktır, çünkü iş katmanınızı uygulayan kodlayıcının istisnayı ele almasını isteyebilirsiniz.

Yayınladığınız örnekte istisnayı yakalamada HİÇBİR NO noktası olsa da tekrarlamak için. Böyle yapma!


1

Maalesef, "geliştirilmiş tasarım" gibi birçok örnek hala korkunç kokuyor veya son derece yanıltıcı olabilir. {} Catch {log; throw} tamamen anlamsızdır. İstisna günlüğü uygulama içinde merkezi bir yerde yapılmalıdır. İstisnalar zaten yığın izini patlatıyor, neden onları sistem sınırlarına yakın bir yere kaydetmiyorsunuz?

Bağlamınızı (belirli bir örnekte DTO) yalnızca günlük iletisine serileştirirken dikkatli olunmalıdır. Günlük dosyalarına erişebilen tüm kişilerin ellerine ulaşmak istemeyebilecek hassas bilgileri kolayca içerebilir. İstisnaya yeni bilgi eklemezseniz, istisna noktasının kaydırılmasını gerçekten görmüyorum. İyi eski Java bunun için bir noktaya sahiptir, arayan kişinin kodu çağırdıktan sonra ne tür istisnalar beklemesi gerektiğini bilmesini gerektirir. .NET'te bu olmadığından, sarma gördüğüm vakaların en az% 80'inde iyi sonuç vermez.


Düşüncen için teşekkürler Joe. Java'da (ve C #, sanırım) TÜM istisnaları (kontrol edilmeyen istisna türleri dahil) yakalanmaya veya ilan edilmeye ilan edilmeye zorlayan sınıf düzeyinde bir açıklama @FaultBoundary görmek isterim. Bu ek açıklamayı her mimari katmanın genel arayüzlerinde kullanırdım. Bu nedenle, @FaultBoundary ThingDAO arabirimi, SQLExceptions, NPE'ler veya AIOB'ler gibi uygulama ayrıntılarını sızdıramaz. Bunun yerine "nedensel" yığın izlemesi günlüğe kaydedilir ve bir DAOSystemException özel durum atılır ... Sistem özel durumunu "kalıcı olarak ölümcül" olarak tanımlıyorum.
corlettk

5
Yakalamak, günlüğe kaydetmek ve sonra tekrar aramak için birçok neden var. Özellikle, catch günlüğüne sahip yöntemde yöntemden çıktıktan sonra kaybedeceğiniz bilgiler varsa. Hata daha sonra ele alınabilir, ancak günlüğe kaydedilemeyebilir ve sistemdeki hatalar hakkında bilgi kaybettiniz.
Andy

1
Bu, Exception sınıfının Data özelliğinin kullanışlı olduğu yerdir - genel günlük kaydı için tüm bu yerel bilgileri yakalamak. Bu makale başlangıçta dikkatimi çekti: blog.abodit.com/2010/03/…
McGuireV10

1

Başkalarının söylediklerini ek olarak, bkz cevabım yakalamak ve yeniden atma no-op olmadığını gösterir (Bu VB, ama kodun bazı C # olabileceğini VB den çağrılan) İlgili bir soruya.


Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan
LHIOUI

@HamzaLH, bunun iyi yazılmış bir cevap olmadığını, ancak diğer cevaplardan ve olumlu oylardan farklı bilgilere sahip olduğunu kabul ediyorum. Yani anlamıyorum, neden silmeyi öneriyorsun? “Konuyla ilgili ve çözüm sunan kısa cevaplar hala cevaplar.” Gönderen meta.stackexchange.com/questions/226258/...
Michael Freidgeim

Bu sadece bağlantı cevabı
LHIOUI

1. Yalnızca bağlantıya verilen yanıtlar, yorumlarda değiştirilmeli, silinmemelidir. 2. Bu, zaman içinde kırılma olasılığı daha düşük olan harici siteye değil, diğer SO sorusuna bir referanstır. 3. “Sadece bağlantı” yapmayan
Michael Freidgeim

1

Cevapların çoğu senaryo hakkında konuşuyor-log-log-rethrow.

Kodunuzda yazmak yerine AOP'yi, özellikle OnExceptionOptions ile Postsharp.Diagnostic.Toolkit'i kullanmayı düşünün IncludeParameterValue ve IncludeThisArgument


Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan
Tony Dong

@TonyDong, bunun iyi yazılmış bir cevap olmadığını, ancak diğer cevaplardan ve olumlu oylardan farklı bilgilere sahip olduğunu kabul ediyorum. Yani anlamıyorum, neden silmeyi öneriyorsun? BTW, 5 yıl sonraki bağlantı hala geçerli. “Konuyla ilgili ve çözüm sunan kısa cevaplar hala cevaplar.” Gönderen meta.stackexchange.com/questions/226258/...
Michael Freidgeim

Stackoverflow yalnızca bu öneriye sahiptir.
Tony Dong

@TonyDong, cevap kesinlikle işe yaramazsa, “Tamam görünüyor” seçeneğini seçmelisiniz
Michael Freidgeim

0

Aracılığıyla istisnalar yeniden atma throwsen sap özgü hata durumlarda bir mantığı var ama diğerlerini atlamak istediğinizde geçerli istisnalar veya durumlarda işlemek için özel bir kod olmadığında yararlıdır.

Misal:

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException)
{
    if (numberText.ToLowerInvariant() == "nothing")
    {
        Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
    }
    else
    {
        throw;
    }
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Bununla birlikte, catch bloklarında koşullu hükümler kullanarak bunu yapmanın başka bir yolu da vardır :

string numberText = "";
try
{
    Console.Write("Enter an integer: ");
    numberText = Console.ReadLine();
    var result = int.Parse(numberText);

    Console.WriteLine("You entered {0}", result);
}
catch (FormatException) when (numberText.ToLowerInvariant() == "nothing")
{
    Console.WriteLine("Please, please don't be lazy and enter a valid number next time.");
}    
finally
{
    Console.WriteLine("Freed some resources.");
}
Console.ReadKey();

Bu mekanizma, yeniden çalışmadan önce .NET çalışma zamanı özel durum nesnesini yeniden oluşturmak zorunda olmadığından, bir özel durumu yeniden atmaktan daha etkilidir.

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.