Özel durum işleme için try catch'i kullanmak en iyi uygulamadır


201

kıdemli bir geliştirici olduğunu iddia eden birinden bile meslektaşımın kodunu korurken, genellikle aşağıdaki kodu görüyorum:

try
{
  //do something
}
catch
{
  //Do nothing
}

veya bazen günlük dosyalarını aşağıdaki try catchblok gibi günlük dosyalarına yazarlar

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);
}

Sadece yaptıklarının en iyi uygulama olup olmadığını merak ediyorum. Beni şaşırttı çünkü düşüncelerimde kullanıcılar sistemde ne olduğunu bilmeli.

Lütfen bana bir tavsiye ver.


128
Snippet # 1, kabul edilemez zamanın% 99,999'udur.
leppie

22
İstisnayı doğrudan kullanıcıya göstermek asla iki nedenden ötürü iyi bir fikir değildir: 1. her zamanki kullanıcı (lar) ise kendisi için çok az şey söyleyen okuma hatası mesajını rahatsız edecektir. 2. Bilgisayar korsanı (bilgisayarları) olarak adlandırılırsa, yararlı bilgiler alabilir. En iyi uygulama, IMO, istisna günlüğü ve kolay hata mesajı göstermektir.
Leri

4
@ leppie Beklenmedik bir şey oluşursa ( uygulama akışının bir parçası gibi NullReferenceveya ArgumentNullbunun bir parçası değilse), düzeltilmesi gereken bir hata olduğu anlamına gelir; böylece bunları günlüğe kaydetmek, kodunuzun daha hızlı hata ayıklamasına yardımcı olur.
Leri

14
Bir istisnayı gizlemek için bir try-catch bloğunun kullanılması genellikle tembel programlamanın sonucudur. Girdileri test etmek için doğrulama kodu yazmak yerine sıklıkla kullanılan bir kısayoldur. Çok zaman zaman, kodunuzun çalışmasını etkilemeyen bir istisnanın ortaya çıkabileceği zamanlar vardır ve bu şekilde gizlemek uygun olabilir. Ancak bu oldukça nadirdir.
Corey

12
@Tamam, eğer bir toplu işse, günlüğe kaydetmek için en üst düzeyde (Ana) yakalarım ve sonra işin anormal bir şekilde sona erdiğine dair bir alarm ayarlamak için yeniden düşünüyorum. Bir web uygulamasıysa, istisna balonunu genel bir işleyiciye bırakıyorum, günlüğe kaydediyor ve kullanıcıyı bir hata ekranına yönlendiriyorum. Kullanım senaryosu senaryo, oturum açtıktan veya başka bir şekilde işledikten sonra bu istisna ile ne yapacağınızı belirler.
Anthony Pegram

Yanıtlar:


300

İstisna yönetim stratejim:

  • İşlenmeyen tüm istisnalarıApplication.ThreadException event , seçeneğine bağlayarak yakalamak için aşağıdakilere karar verin:

    • Bir UI uygulaması için: kullanıcıya bir özür mesajı (winforms) ile açmak
    • Hizmet veya Konsol uygulaması için: bir dosyaya (hizmet veya konsol) günlüğe kaydetme

Sonra hep içine dışarıdan çalıştırılan kodun her parçası içinde try/catch:

  • Winforms altyapısı tarafından başlatılan tüm etkinlikler (Yükle, Tıkla, SeçiliDeğiştir ...)
  • Üçüncü taraf bileşenleri tarafından tetiklenen tüm etkinlikler

Sonra 'dene / yakala'

  • Bütün Bunu işlemleri her zaman işe yaramayabilir biliyorum (IO işlemlerini potansiyel sıfıra bölüm ... ile hesaplamalar). Böyle bir durumda, ApplicationException("custom message", innerException)gerçekte ne olduğunu takip etmek için yeni bir şey atıyorum

Ayrıca, istisnaları doğru bir şekilde sıralamak için elimden geleni yapıyorum . İstisnalar vardır:

  • kullanıcıya hemen gösterilmesi gerekir
  • basamaklı sorunlardan kaçınmak için bir şeyleri bir araya getirmek için biraz ek işlem gerektirir (yani: .DndUpdate'i doldurma finallysırasında bölüme koyun TreeView)
  • kullanıcı umursamaz, ama ne olduğunu bilmek önemlidir. Bu yüzden her zaman onları kaydederim:

    • Olay günlüğünde
    • veya diskteki bir .log dosyasında

Uygulama üst düzey hata işleyicilerindeki özel durumları işlemek için bazı statik yöntemler tasarlamak iyi bir uygulamadır .

Ayrıca kendimi de denemeye zorlarım:

  • TÜM istisnaların en üst seviyeye kadar oluşturulduğunu unutmayın . İstisna işleyicilerini her yere koymak gerekli değildir.
  • Yeniden kullanılabilir veya derin olarak adlandırılan işlevlerin özel durumları görüntülemesine veya günlüğe kaydetmesine gerek yoktur: bunlar otomatik olarak oluşturulur veya özel durum işleyicilerimdeki bazı özel iletilerle yeniden oluşturulur.

En sonunda :

Kötü:

// DON'T DO THIS, ITS BAD
try
{
    ...
}
catch 
{
   // only air...
}

Faydasız:

// DONT'T DO THIS, ITS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

Sonunda bir yakalama olmadan denemek tamamen geçerli:

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

En üst düzeyde yaptığım:

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(); // Log exception

    -- OR --

    ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

Bazı denilen işlevlerde ne yapıyorum:

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

İstisna işleme (Özel İstisnalar) ile ilgili çok şey var, ancak aklımda tutmaya çalıştığım kuralların yaptığım basit uygulamalar için yeterli olduğunu unutmayın.

Aşağıda, yakalanan istisnaları rahat bir şekilde ele alan uzantı yöntemlerine bir örnek verilmiştir. Birlikte zincirlenebilecekleri bir şekilde uygulanırlar ve kendi yakalanan istisna işleminizi eklemek çok kolaydır.

// Usage:

try
{
    // boom
}
catch(Exception ex)
{
    // Only log exception
    ex.Log();

    -- OR --

    // Only display exception
    ex.Display();

    -- OR --

    // Log, then display exception
    ex.Log().Display();

    -- OR --

    // Add some user-friendly message to an exception
    new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
    File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
    return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
    MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
    return ex;
}

98
catch(Exception ex) { throw ex; }C # ' da gereksizden daha kötüdür (yakaladığınız istisna türünden bağımsız olarak). Tekrarlamak için kullanın throw;. throw exBirincisi ile istisna, kendinizden kaynaklanmış gibi görünecek , ikincisiyle ise orijinal throwifadeden düzgün bir şekilde çıkacaktır .
CVn

2
Neden Application.ThreadExceptionetkinliği bağlarsınız ve her istisnayı a ile kaydırırsınız catch(Exception ex) {ex.Log(ex);}. Muhtemelen birincisinin mükemmel bir uygulama olduğunu kabul ediyorum, ancak ikincisi hata günlüklerinizi çoğaltma riskini ekler ve istisnanın gerçekleştiğini gizler. Ayrıca throw exçok çok kötü.
Keith

1
Catch (Exception ex) {ex ex; yararsız olmak. Bu yüzden "artık", "Bunu yapma" ifadesi için en iyi kelime olmadığını varsayalım. Bu yüzden yazıyı, try-catch'in ilk iki örneğinden kaçınılması gerektiğini daha iyi ifade etmek için biraz değiştirdim.
Larry

3
Harika ve yapıcı bir cevap, en önemlisi Sadece hava ifade zevk aldım :) Ve Application.ThreadExceptionolay için teşekkürler , bunun farkında değildi, çok yararlı.
Mehdi Tahsildari


61

En iyi uygulama, istisna işlemenin sorunları asla gizlememesi gerektiğidir . Bu, try-catchblokların son derece nadir olması gerektiği anlamına gelir .

Bir try-catchmantık kullanmanın mantıklı olduğu 3 durum vardır .

  1. Her zaman mümkün olduğu kadar düşük bilinen istisnalarla ilgilenin . Bununla birlikte, bir istisna bekliyorsanız, öncelikle test etmek genellikle daha iyi bir uygulamadır. Örneğin ayrıştırma, biçimlendirme ve aritmetik istisnalar, belirli bir durumdan ziyade, önce mantık denetimleri ile neredeyse her zaman daha iyi işlenir try-catch.

  2. İstisnada bir şey yapmanız gerekiyorsa (örneğin, bir işlemi günlüğe kaydetme veya bir işlemi geri alma), istisnayı yeniden atar.

  3. Her zaman olabildiğince yüksek bilinmeyen istisnalar ile uğraşın - bir istisna tüketmeli ve tekrar atmaması gereken tek kod UI veya genel API olmalıdır.

Uzak bir API'ya bağlandığınızı varsayalım, burada belirli hatalar beklediğinizi biliyorsunuz (ve bu durumlarda bir şeyler var), bu yüzden durum 1:

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

Beklenmediklerinden başka bir istisna yakalanmadığını unutmayın.

Şimdi veritabanına bir şey kaydetmeye çalıştığınızı varsayalım. Başarısız olursa geri almalıyız, bu yüzden durum 2'ye sahibiz:

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

İstisnayı yeniden attığımızı unutmayın - daha yüksek olan kodun hala bir şeyin başarısız olduğunu bilmesi gerekir.

Sonunda kullanıcı arayüzümüz var - burada tamamen ele alınmayan istisnalar istemiyoruz, ancak onları da gizlemek istemiyoruz. Burada durum 3'e bir örnek verelim:

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

Bununla birlikte, çoğu API veya UI çerçevesinin durum 3 yapmanın genel yolları vardır. Örneğin, ASP.Net'in istisna ayrıntılarını döken sarı bir hata ekranı vardır, ancak bu, üretim ortamında daha genel bir mesajla değiştirilebilir. Bunları izlemek en iyi yöntemdir çünkü size çok fazla kod tasarrufu sağlar, ancak aynı zamanda hata günlüğü ve ekran sabit kodlu değil yapılandırma kararları olmalıdır.

Bu, durum 1'in (bilinen istisnalar) ve durum 3'ün (bir defalık kullanıcı arayüzü işleme) her ikisinin de daha iyi desenlere sahip olduğu anlamına gelir (beklenen hatayı önleyin veya kullanıcı arayüzüne el hatası işlenmesini önleyin).

Durum 2 bile daha iyi kalıplarla değiştirilebilir, örneğin işlem kapsamları ( usingblok sırasında işlenmeyen herhangi bir işlemi geri alan bloklar) geliştiricilerin en iyi uygulama modelini yanlış anlamasını zorlaştırır.

Örneğin, büyük ölçekli bir ASP.Net uygulamanız olduğunu varsayalım. Hata kaydı ELMAH üzerinden olabilir , hata göstergesi yerel olarak bilgilendirici bir YSoD ve üretimde hoş bir yerelleştirilmiş mesaj olabilir. Veritabanı bağlantılarının tümü işlem kapsamları ve usingbloklar aracılığıyla yapılabilir . Tek bir try-catchbloğa ihtiyacınız yok .

TL; DR: En iyi uygulama aslında hiç try-catchblok kullanmamaktır .


4
@Jorj tüm yazıyı okumalısınız ve hala aynı fikirde değilseniz, sonucumdan hoşlanmadığınızı belirtmek yerine destekleyici argümanlarımdan birine karşı koymak daha yapıcı olacaktır. Neredeyse her zaman daha iyi bir model vardır try-catch- (çok nadiren) yararlı olabilir ve bunları asla kullanmamanız gerektiğini savunmuyorum, ancak zamanın% 99'u daha iyi bir yol var.
Keith

Şimdiye kadarki en iyi cevap - neredeyse her .net geliştirme türü, küresel düzeyde istisnalarla uğraşmak için çok daha uygun olan bir çeşit HANDLER'a sahiptir, bu da onları tutarlı bir şekilde ele almayı ve aynı zamanda patlamasına izin vermeyi çok daha kolay hale getirir kadar geliştirme (neden kimse bir yığın izleme için bir günlük dosyası kazmak istesin ??) @Kieth, ben TLDR ile yol ve küresel işleyicileri bazı örnekleri (yani ThreadException, Application_Error, vb) eklemek istiyorum.
Elbette

34

Bir istisna engelleme hatasıdır .

Her şeyden önce, en iyi uygulama , bir engelleme hatası olmadığı sürece, herhangi bir hata için istisna atmayın .

Hata engelleniyorsa , istisnayı atın. İstisna çoktan atıldıktan sonra, gizlenmesine gerek yoktur, çünkü olağanüstüdür; kullanıcıya bunu bildirin (kullanıcı arayüzünde kullanıcı için yararlı bir şey için tüm istisnayı yeniden biçimlendirmeniz gerekir).

Yazılım geliştiricisi olarak işiniz, bir parametre veya çalışma zamanı durumunun bir istisnada sona erebileceği istisnai bir durumu önlemeye çalışmaktır . Yani, istisnalar yoksayılmamalı, ancak bunlardan kaçınılmalıdır .

Örneğin, bazı tamsayı girdilerinin geçersiz bir biçimde gelebileceğini biliyorsanız , int.TryParseyerine kullanın int.Parse. "Başarısız olursa, sadece bir istisna atın" demek yerine bunu yapabileceğiniz birçok durum vardır.

İstisnaları atmak pahalıdır.

Ne de olsa, bir istisna atılırsa, istisnayı atıldıktan sonra günlüğe yazmak yerine, en iyi uygulamalardan biri ilk şans istisnası işleyicisinde onu yakalamaktır . Örneğin:

  • ASP.NET: Global.asax Uygulama_ Hatası
  • Diğerleri: AppDomain.FirstChanceException olayı .

Benim duruşum, yerel denemelerin / yakalamaların, bir istisnayı başka bir duruma çevirebileceğiniz veya çok, çok, çok, çok, çok özel bir durum ("kütüphane hatası") için "sessizleştirmek" istediğiniz özel durumları ele almak için daha uygun olduğudur. tüm hatayı gidermek için susturmanız gereken alakasız bir istisna atma).

Geri kalan davalar için:

  • İstisnalardan kaçınmaya çalışın.
  • Bu mümkün değilse: birinci şans istisna işleyicileri.
  • Veya bir Keskinleştirme Sonrası yönü (AOP) kullanın.

Bazı yorumlarda @thewhiteambit yanıtlanıyor ...

@thewhiteambit dedi:

İstisnalar Önemli Hatalar değildir, İstisnalardır! Bazen onlar bile Hata değildir, ancak onları dikkate almak, Ölümcül Hatalar, İstisnaların ne olduğunu tamamen yanlış anlamaktır.

Her şeyden önce, bir istisna nasıl bir hata olamaz?

  • Veritabanı bağlantısı yok => istisna.
  • Bazı type => özel durumlarına ayrıştırmak için geçersiz dize biçimi
  • JSON ayrıştırılmaya çalışılıyor ve girdi aslında JSON => özel durumu değil
  • nullNesne bekleniyorken argüman => istisna
  • Bazı kitaplıklarda hata var => beklenmeyen bir istisna atar
  • Bir soket bağlantısı var ve bağlantısı kesiliyor. Sonra bir mesaj göndermeye çalışıyorsunuz => istisna
  • ...

Bir istisna atıldığında 1k durumlarını listeleyebiliriz ve sonuçta olası durumlardan herhangi biri bir hata olacaktır .

Bir istisna olduğu günün sonunda o tanısal bilgi toplar bir nesne olduğu için, bir hata - bir mesajı var ve bir şeyler yanlış gittiğinde o olur.

İstisnai bir durum olmadığında hiç kimse bir istisna fırlatamaz. İstisnalar hataları engellemelidir, çünkü atıldıktan sonra, kullanmaya çalışın / yakalayın ve kontrol akışını uygulamak için istisnalar , uygulama / hizmetinizin istisnai bir duruma giren işlemi durduracağı anlamına gelir .

Ayrıca, herkese Martin Fowler tarafından yayınlanan (ve Jim Shore tarafından yazılan) hızlı paradigmayı kontrol etmesini öneriyorum . Bu belgeye bir süre önce gelmeden önce bile istisnaları nasıl ele aldığımı hep anladım.

[...] onları düşünün Ölümcül Hatalar istisnaların tamamen yanlış bir anlayıştır.

Genellikle istisnalar bazı işlem akışlarını azaltır ve bunları insan tarafından anlaşılabilir hatalara dönüştürmek için kullanılır. Bu nedenle, bir istisna aslında hata vakalarını ele almak ve bir uygulama / hizmet tam çökmesini önlemek ve kullanıcı / tüketiciye bir şeyler ters gittiğini bildirmek için üzerinde çalışmak için daha iyi bir paradigma gibi görünüyor.

@Thewhiteambit ile ilgili daha fazla cevap

Örneğin, Veritabanı Bağlantısının eksik olması durumunda, program istisnai olarak yerel bir dosyaya yazmaya devam edebilir ve değişiklikleri yeniden kullanılabilir duruma geldiğinde Veritabanına gönderebilir. Geçersiz Dize-Sayı dökümünüz, Ayrıştırma ("1,5") için varsayılan İngilizce dilinin başarısız olması ve tamamen Almanca yorumuyla denemeniz gibi, İstisnada dil-yerel yorumuyla yeniden ayrıştırmaya çalışılabilir. çünkü ayırıcı olarak nokta yerine virgül kullanıyoruz. Bu İstisnaların engellememesi gerektiğini görüyorsunuz, sadece İstisna işlemeye ihtiyaçları var.

  1. Uygulamanız veritabanına veri göndermeden çevrimdışı çalışabiliyorsa , kontrol akışını kullanmak bir anti-desen olarak kabul edildiğinden istisnalar kullanmamalısınız try/catch. Çevrimdışı çalışma olası bir kullanım durumudur, bu nedenle veritabanına erişilebilir olup olmadığını kontrol etmek için kontrol akışı uygularsınız, erişilemez olana kadar beklemezsiniz .

  2. Ayrıştırma şey de beklenen bir durum (olan OLAĞANÜSTÜ değil DURUM ). Bunu bekliyorsanız, kontrol akışını gerçekleştirmek için istisnalar kullanmazsınız! . Kullanıcıdan kültürünün ne olduğunu bilmek için bazı meta veriler alırsınız ve bunun için biçimlendiriciler kullanırsınız! .NET, bu ve diğer ortamları da destekler ve uygulamanızın / hizmetinizin kültüre özgü kullanımını bekliyorsanız, sayı biçimlendirmesinden kaçınılması gerektiğinden bir istisna oluşturur .

İşlenmeyen bir Kural Dışı Durum genellikle Hata olur, ancak Kural Dışı Durumların kendisi codeproject.com/Articles/15921/Not-All-Exceptions-Are-Errors değildir

Bu makale sadece yazarın görüşü ya da görüşüdür.

Vikipedi de sadece artikül yazar (lar) ının görüşü olabileceğinden, bunun dogma olduğunu söyleyemem , ancak istisna makaleye göre Kodlama'nın bazı paragraflarda bir yerde ne dediğini kontrol ederim :

[...] Programa devam etmek için ortaya çıkan belirli hataları işlemek için bu istisnaları kullanmaya istisna ile kodlama denir. Bu anti-desen yazılımı performans ve sürdürülebilirlik açısından hızla bozabilir.

Ayrıca bir yerde şöyle diyor:

Yanlış istisna kullanımı

Genellikle istisna ile kodlama, yanlış istisna kullanımıyla yazılımda başka sorunlara yol açabilir. Benzersiz bir sorun için kural dışı durum işleme kullanımına ek olarak, kural dışı durum kullanımı, kural dışı durum yükseltildikten sonra bile kod yürüterek bunu daha da ileri götürür. Bu zayıf programlama yöntemi, birçok yazılım dilinde goto yöntemine benzer, ancak yalnızca yazılımda bir sorun algılandıktan sonra gerçekleşir.

Dürüst olmak gerekirse, yazılımın geliştirilemeyeceğine inanıyorum. Bunu biliyorsan ...

  • Veritabanınız çevrimdışı olabilir ...
  • Bazı dosyalar kilitlenebilir ...
  • Bazı biçimlendirme desteklenmiyor olabilir ...
  • Bazı alan adı doğrulaması başarısız olabilir ...
  • Uygulamanız çevrimdışı modda çalışmalıdır ...
  • ne olursa olsun ...

... bunun için istisnalar kullanmayacaksınız . Sen olur destekleyen düzenli kontrol akışını kullanarak bu kullanım durumları.

Ve bazı beklenmedik kullanım durumları kapsanmazsa, kodunuz hızlı bir şekilde başarısız olur, çünkü bir istisna atar . Doğru, çünkü bir istisna istisnai bir durumdur .

Öte yandan ve son olarak, bazen beklenen istisnaları atan istisnai durumları kapsarsınız , ancak bunları kontrol akışını uygulamak için atmazsınız. Bunu, üst katmanları bazı kullanım durumlarını desteklemediğinizi bildirmek istediğiniz için veya kodunuz belirli argümanlarla veya ortam verileri / özellikleriyle çalışmazsa bildirirsiniz.


6

Kullanıcılarınızı kodda olan bir şey hakkında endişelenmeniz gereken tek zaman, sorunu önlemek için yapabilecekleri veya yapmaları gereken bir şey olup olmadığıdır. Bir formdaki verileri değiştirebilirlerse, sorunu önlemek için bir düğmeye basın veya bir uygulama ayarını değiştirin, ardından onlara bildirin. Ancak kullanıcının kaçınma yeteneğine sahip olmadığı uyarılar veya hatalar, yalnızca ürününüze olan güvenini kaybetmelerini sağlar.

İstisnalar ve Günlükler sizin için geliştiricidir, son kullanıcınız değildir. Her bir istisnayı yakaladığınızda yapılacak doğru şeyi anlamak, sadece bazı altın kurallar uygulamaktan veya uygulama genelinde bir güvenlik ağına güvenmekten çok daha iyidir.

Dikkatsiz kodlama SADECE yanlış kodlama türüdür. Bu durumlarda yapılabilecek daha iyi bir şey olduğunu hissetmeniz, iyi kodlamaya yatırım yaptığınızı gösterir, ancak bu durumlarda bazı genel kuralları damgalamaktan kaçının ve bir şeyin ilk etapta atma nedenini anlamaya çalışmayın. ondan kurtulmak için yapabilirsiniz.


6

Bunun eski bir soru olduğunu biliyorum, ama burada kimse MSDN makalesinden bahsetmedi ve aslında benim için temizleyen belge oldu, MSDN bu konuda çok iyi bir belgeye sahip , aşağıdaki koşullar geçerli olduğunda istisnaları yakalamanız gerekir:

  • Özel durumun neden atılabileceğini iyi anlarsınız ve bir FileNotFoundException nesnesini yakaladığınızda kullanıcıdan yeni bir dosya adı girmesini istemek gibi belirli bir kurtarma işlemi uygulayabilirsiniz.

  • Yeni, daha belirgin bir istisna oluşturabilir ve atayabilirsiniz.

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}
  • Ek işleme için geçmeden önce bir istisnayı kısmen ele almak istersiniz. Aşağıdaki örnekte, özel durumu yeniden atmadan önce bir hata günlüğüne girdi eklemek için bir catch bloğu kullanılır.
    try
{
    // Try to access a resource.
}
catch (System.UnauthorizedAccessException e)
{
    // Call a custom error logging procedure.
    LogError(e);
    // Re-throw the error.
    throw;     
}

" İstisnalar ve İstisna İşleme " bölümünün tamamını ve ayrıca İstisnalar için En İyi Uygulamaları okumanızı öneririm .


1

Daha iyi olan yaklaşım ikincisidir (istisna türünü belirttiğiniz yaklaşım). Bunun avantajı, kodunuzda bu tür özel durumların oluşabileceğini bilmenizdir. Bu tür bir istisnayı yönetiyorsunuz ve devam edebilirsiniz. Başka bir istisna gelirse, kodunuzdaki hataları bulmanıza yardımcı olacak bir şey yanlış demektir. Uygulama sonunda çökecek, ancak kaçırmanız gereken (hata) düzeltilmesi gereken bir şey olduğunu öğreneceksiniz.


1

İstisnalar ile aşağıdakileri denerim:

İlk olarak, sıfıra bölme, G / Ç işlemleri gibi özel durumları yakalarım ve buna göre kod yazarım. Örneğin, değerlerin provizyonuna bağlı olarak sıfıra bölme kullanıcıyı uyarabilirim (örneğin orta hesaplamada (bağımsız değişkenler değil) basit bir hesap makinesi sıfıra bölünerek gelir) veya bu istisnayı sessizce tedavi etmek için, günlüğe kaydetme işlemeye devam edin.

Sonra kalan istisnaları yakalamaya ve günlüğe kaydetmeye çalışıyorum. Mümkünse kodun yürütülmesine izin verin, aksi takdirde kullanıcıyı bir hata oluştuğu konusunda uyarın ve hata raporu göndermelerini isteyin.

Kodda, şöyle bir şey:

try{
    //Some code here
}
catch(DivideByZeroException dz){
    AlerUserDivideByZerohappened();
}
catch(Exception e){
    treatGeneralException(e);
}
finally{
    //if a IO operation here i close the hanging handlers for example
}

1
Sıfır istisnalara bölün ve benzerleri, a 0yerine önceden bir pay kontrol ederek daha iyi ele alınır try-catch. Ayrıca neden jenerik Exceptionburada yakalamak ? Beklemediğiniz tüm durumlarda burada hata balonunu bırakmaktan daha iyidir.
Keith

Ben verdiğim örnek hakkında ne yazdıklarını daha iyi okuyun - "argümanlarda değil" dikkat edin. Elbette herhangi bir hesap makinesi verilen argümanları doğrulamalıdır. Konuştuğum şey orta adımlardı. Bu noktada, kullanıcı argümanı doğrulaması zaten gerçekleşti. Ayrıca bazı uygulamalarda, kabarma istisnalarından kaçınmak daha iyidir. Bazı uygulamalar istisnaları sessizce ele alırken, diğerleri istisnaları hata olarak ele almalıdır. Örneğin bir web sunucusu, istisnalar meydana geldiğinde bile çalışmalıdır; burada istisnalar oluştuğunda tıbbi yazılım (örneğin x-ray makineleri) iptal edilmelidir.
Sorcerer86pt

Uygulama yok edilmelidir şimdiye sessizce istisnalar davranın. Bazen kodun işleyebileceği bir istisnanız vardır, ancak bu tür kullanım hem nadir hem de beklenen istisnaya özgü olmalıdır. Bir web sunucusu örneğiniz kötüdür - hataların nasıl günlüğe kaydedileceğini ve ayrıntılarla mı yoksa yalnızca bir HTTP 500 sayfasıyla mı görüntüleneceğini seçmenize izin veren yapılandırma ayarlarına sahip olmalıdır, ancak hataları hiçbir zaman sessizce göz ardı etmemelidir .
Keith

İnsanları gerçekten "goto" için bir eşanlamlı daha eklemeye neyin motive ettiğini anlamaya çalışıyorum. Ancak sıfıra bölme ile ilgili olarak, bu, dil geliştirmeyi haklı gösteren TEK istisna olabilir. Neden? A) sıfırın veri kümenizde istatistiksel olarak sonsuz olması ve B) bir istisna kullanmak (izin vermek) çok daha verimli olabilir, çünkü bölünme yapmak sıfır böleni test etmenin bir yoludur. A ve B doğru olduğunda, programınızın ortalama yürütülmesi bir istisna kullanarak daha hızlı olur ve hatta daha küçük olabilir.
Mike Layton

1

İkinci yaklaşım iyi bir yaklaşımdır.

Hatayı göstermek ve kendisiyle ilgili olmayan çalışma zamanı istisnasını (yani hata) göstererek uygulamanın kullanıcısını karıştırmak istemiyorsanız, sadece günlük hatasını ve teknik ekip sorunu arayabilir ve çözebilir.

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);//it will write the or log the error in a text file
}

Tüm başvurunuz için ikinci yaklaşıma gitmenizi tavsiye ederim.


2
İkinci yaklaşım kullanıcıyı bir hatadan daha fazla göstermez - örneğin bir şey kaydediyorlarsa başarısız olduğunu bilemezlerdi. catchbloklar her zaman ya throwistisnayı başlatır ya da bir şey döndürür / kullanıcıya eylemin başarısız olduğunu bildiren bir şey görüntüler. Destek çağrısını, ne olursa olsun kaydedemedikleri zaman almak istersiniz, 6 ay sonra geri almaya çalıştıklarında ve bulamazlar.
Keith

0

Boş bırakma bloğunu bırakmak en kötü şeydir. Bir hata varsa, bunu işlemenin en iyi yolu:

  1. Dosya \ veritabanı vb. İçine girin.
  2. Anında düzeltmeye çalışın (belki de bu işlemi yapmanın alternatif yolunu deneyin)
  3. Bunu düzeltemezsek, kullanıcıya bir hata olduğunu bildirin ve elbette işlemi iptal edin

0

Bana göre, istisnaları ele almak iş kuralı olarak görülebilir. Açıkçası, ilk yaklaşım kabul edilemez. İkincisi daha iyidir ve bağlam böyle söylüyorsa% 100 doğru olabilir. Örneğin, şimdi bir Outlook Eklentisi geliştiriyorsunuz. Eğer addin işlenmeyen bir istisna atarsa, outlook kullanıcısı bunu şimdi biliyor olabilir çünkü bir eklenti başarısız olduğu için outlook kendini yok etmeyecektir. Ve neyin yanlış gittiğini anlamak için zor zamanlarınız var. Bu nedenle, bu durumda ikinci yaklaşım, bana göre, bu doğru bir yaklaşımdır. İstisna günlüğünün yanı sıra, hata mesajını kullanıcıya göstermeye karar verebilirsiniz - bunu bir iş kuralı olarak kabul ediyorum.


0

En iyi uygulama, hata oluştuğunda bir İstisna atmaktır. Çünkü bir hata oluştu ve gizlenmemelidir.

Ancak gerçek hayatta bunu gizlemek istediğinizde birkaç durumunuz olabilir

  1. Üçüncü taraf bileşenlere güveniyorsunuz ve hata durumunda programa devam etmek istiyorsunuz.
  2. Hata durumunda devam etmeniz gereken bir iş vakanız var

6
Hayırdeğil atmak Exception. Hiç. Exceptionİstediğiniz her şeyin uygun bir alt sınıfını atın , ancak asla Exceptionkesinlikle semantik bilgi vermediğinden . Ben düz atmak mantıklı bir senaryo göremiyorum Exceptionama bir alt sınıf değil.
CVn


0

catchArgümansız basitçe edilir yeme istisna ve hiçbir faydası yoktur. Önemli bir hata oluşursa ne olur? Tartışma olmadan yakalama kullanırsanız ne olduğunu bilmenin bir yolu yoktur.

Bir catch deyimi daha yakalamak gerektiğini spesifik gibi İstisnalar FileNotFoundExceptionve sonra çok sonlandırmak Eğer yakalamak gerekir Exceptionbaşka durum yakalamak ve bunları oturum hangi.


catch(Exception)Sonunda neden bir general var ? Eğer beklemiyorsanız, bir sonraki katmana geçirmek her zaman en iyi uygulamadır.
Keith

1
@Evet evet haklısın ... Beklemediğiniz istisnaları yakalamanın bir anlamı yok ama günlük kaydı için genel istisna yapabilirsiniz ..
Anirudha

0

Bazen kullanıcılara hiçbir şey söylemeyen istisnaları tedavi etmeniz gerekir.

Benim yolum:

  • Kritik istisnalar için uygulama düzeyinde (yani global.asax'ta) yakalanmamış istisnaları yakalamak için (uygulama yararlı olamaz). Bu muafiyetleri yerinde yakalamıyorum. Sadece uygulama düzeyinde oturum açın ve sistemin işini yapmasına izin verin.
  • "Yerinde" yakalayın ve kullanıcıya bazı yararlı bilgiler gösterin (yanlış numara girildi, ayrıştırılamıyor).
  • Yerinde yakalamak ve "Ben arka plan üzerinde güncelleme bilgilerini kontrol edecek, ancak hizmet çalışmıyor" gibi marjinal sorunlar üzerinde hiçbir şey yapmayın.

Kesinlikle en iyi uygulama olması gerekmez. ;-)


0

Sana bir şey söyleyebilirim:

Snippet # 1 kabul edilemez çünkü istisna göz ardı edilir. (hiçbir şey olmamış gibi yutuyor).

Bu yüzden hiçbir şey yapmayan ya da sadece tekrarlayan catch bloğu eklemeyin.

Yakalama bloğu bir değer katmalıdır. Örneğin son kullanıcıya çıkış mesajı veya kayıt hatası.

Normal akış programı mantığı için istisna kullanmayın. Örneğin:

örneğin, giriş doğrulaması. <- Bu geçerli istisnai bir durum değil, IsValid(myInput);giriş öğesinin geçerli olup olmadığını kontrol etmek için yöntem yazmalısınız .

İstisnadan kaçınmak için kod tasarlayın. Örneğin:

int Parse(string input);

İnt değerine ayrıştırılamayan bir değer iletirsek, bu yöntem atılır ve istisna olur, bunun yerine şöyle bir şey yazabiliriz:

bool TryParse(string input,out int result); <- bu yöntem, çözümlemenin başarılı olup olmadığını gösteren boole döndürür.

Belki bu biraz bu sorunun kapsamı dışındadır, ancak umarım bu konu hakkında try {} catch(){}ve istisnalar olduğunda doğru kararlar vermenize yardımcı olacaktır .

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.