Bir Windows Forms Uygulamasında Özel Durum İşleme İçin En İyi Uygulama?


118

Şu anda ilk Windows Forms uygulamamı yazma sürecindeyim. Şimdi birkaç C # kitabı okudum, bu yüzden C # 'ın istisnalarla hangi dil özelliklerinin üstesinden gelmesi gerektiğini görece iyi bir şekilde anladım. Ancak hepsi oldukça teoriktir, bu yüzden henüz sahip olmadığım şey, uygulamamda temel kavramları iyi bir istisna işleme modeline nasıl çevireceğime dair bir his.

Konuyla ilgili herhangi bir bilgelik bilgisini paylaşmak isteyen var mı? Benim gibi yeni başlayanların yaptığını gördüğünüz yaygın hataları ve istisnaların ele alınmasına ilişkin genel tavsiyeleri uygulamamı daha kararlı ve sağlam olacak şekilde gönderin.

Şu anda çözmeye çalıştığım ana şeyler:

  • Bir istisnayı ne zaman yeniden atmalıyım?
  • Bir tür merkezi hata işleme mekanizmasına sahip olmaya çalışmalı mıyım?
  • Diskte bir dosyanın mevcut olup olmadığı gibi şeyleri önceden test etmekle karşılaştırıldığında, fırlatılabilecek istisnaların işlenmesi performans düşüşüne neden oluyor mu?
  • Tüm yürütülebilir kodlar, dene-yakala bloklarının içine alınmalı mı?
  • Boş bir yakalama bloğunun kabul edilebilir olabileceği zamanlar var mı?

Tüm tavsiyeler minnetle alındı!

Yanıtlar:


79

Birkaç bit daha ...

Kesinlikle bir merkezi istisna işleme politikasına sahip olmalısınız. Bu, Main()bir dene / yakala işlemine sarmak kadar basit olabilir ve kullanıcıya zarif bir hata mesajı vererek hızlı bir şekilde başarısız olabilir. Bu, "son çare" istisna işleyicidir.

Önleyici kontroller, mümkünse her zaman doğrudur, ancak her zaman mükemmel değildir. Örneğin, bir dosyanın varlığını kontrol ettiğiniz kod ile onu açtığınız sonraki satır arasında, dosya silinmiş olabilir veya başka bir sorun erişiminizi engelleyebilir. Hala o dünyada dene / yakala / nihayet ihtiyacın var. Hem önleyici kontrolü hem de uygun şekilde dene / yakala / sonunu kullanın.

Bir istisnayı asla "yutmayın", en iyi belgelenmiş durumlar dışında, atılan istisnanın yaşanabilir olduğundan kesinlikle emin olduğunuzda. Bu neredeyse asla böyle olmayacak. (Ve eğer öyleyse, yalnızca belirli istisna sınıfını yuttuğunuzdan emin olun - asla yutmayın System.Exception.)

Kitaplıklar oluştururken (uygulamanız tarafından kullanılır), istisnaları yutmayın ve istisnaların ortaya çıkmasına izin vermekten korkmayın. Eklemek için yararlı bir şeyiniz olmadıkça tekrar atmayın. Bunu asla (C # ile) yapmayın:

throw ex;

Çağrı yığınını sileceğiniz gibi. Yeniden atmanız gerekiyorsa (bu, Enterprise Kitaplığının İstisna İşleme Bloğunu kullanırken olduğu gibi ara sıra gereklidir), aşağıdakileri kullanın:

throw;

Günün sonunda, çalışan bir uygulama tarafından atılan istisnaların büyük çoğunluğu bir yerde açığa çıkmalıdır. Son kullanıcılara ifşa edilmemelidirler (genellikle özel veya başka şekilde değerli veriler içerdikleri için), bunun yerine yöneticilerin istisnadan haberdar edilmesiyle, genellikle günlüğe kaydedilmelidirler. Kullanıcıya işleri basitleştirmek için genel bir iletişim kutusu, belki bir referans numarası sunulabilir.

.NET'te istisna yönetimi bilimden çok sanattır. Herkesin burada paylaşmak için favorileri olacak. Bunlar, 1. günden beri .NET kullanarak edindiğim ipuçlarından sadece birkaçı, pastırmamı birden fazla seferde kurtaran teknikler. Kilometreniz değişebilir.


1
İstisnaların köpürmesine izin verilirse, arayanın istisnanın bir işlemin başarısız olduğunu gösterip göstermediğini nasıl bilmesi gerekir, ancak sistem temelde iyi durumda (örneğin, bir kullanıcı bozuk bir belge dosyasını açmaya çalıştı; dosya yüklenmiyor ama her şey) yoksa iyi olmalı) ya da CPU'nun yandığını ve birinin mümkün olduğunca hızlı bir şekilde çıkışlara yönelmesi gerektiğini mi gösteriyor? ArgumentException gibi bir şey, atıldığı koşullara bağlı olarak ikisini de gösterebilir.
supercat

2
@supercat ApplicationExceptionUygulamanın makul bir şekilde ayırt edebilmesi ve ele alabilmesi gereken hata durumları için belirli alt sınıflar yazarak .
Matt Enright

@Matt Enright: Birinin kendi istisnalarını yakalaması kesinlikle mümkün, ancak istisnalar atan modüllerin, başarısızlığın ima edilenin ötesinde herhangi bir durumun yolsuzluğunu gösterip göstermediğini gösteren bir kongreye uzaktan benzeyen herhangi bir şeyden habersizim. İdeal olarak, SuperDocument.CreateFromFile () gibi bir yöntem başarılı olur, bir CleanFailure istisnası atar veya bir SomethingReallyBadHappenedException oluşturur. Ne yazık ki, kendi catch bloğu içinde bir özel durum bir sarar her şeyi sürece, bir ınvalidoperationexception olsun ... bilmenin bir yolu yoktur
SuperCat

@Matt Enright: ... bir CleanFailureException veya SomethingReallyBadHappenedException içine sarılmalıdır. Ve her şeyi ayrı deneme bloklarına sarmak, ilk başta istisnalara sahip olma amacının tamamını ortadan kaldıracaktır.
supercat

2
Bunun hatalı bir istisna türü ile hata modlarını gizlemek için zayıf bir kütüphane tasarımı olduğunu düşünüyorum. Uygulamanın her duruma farklı yanıt vermesi gerektiğinden, gerçekten kastettiğiniz bir IOException veya InvalidDataException ise FileNotFoundException oluşturmayın. StackOverflowException veya OutOfMemoryException gibi şeyler bir uygulama tarafından makul bir şekilde ele alınamaz, bu yüzden onları kabarcıklara bırakın, çünkü iyi huylu bir uygulama zaten merkezi "son çare" işleyiciye sahiptir.
Matt Enright

63

Burada harika bir CodeProject makalesi var . İşte birkaç önemli nokta:

  • En kötüsünü planlayın *
  • Erken kontrol et
  • Dış verilere güvenmeyin
  • Tek güvenilir cihazlar: video, fare ve klavye.
  • Yazılar da başarısız olabilir
  • Güvenle Kodlayın
  • Yeni İstisna atmayın ()
  • Mesaj alanına önemli istisna bilgileri koymayın
  • İş parçacığı başına tek bir yakalama (istisna istisna) koyun
  • Yakalanan Genel İstisnalar yayınlanmalıdır
  • Log Exception.ToString (); asla yalnızca Exception.Message günlüğe kaydetme!
  • İş parçacığı başına (İstisna) birden fazla yakalama
  • İstisnaları asla yutmayın
  • Temizleme kodu son bloklara yerleştirilmelidir
  • Her yerde "kullanarak" kullanın
  • Hata koşullarında özel değerler döndürmeyin
  • Kaynağın olmadığını belirtmek için istisnalar kullanmayın
  • Bir yöntemden bilgi döndürmek için istisna işlemeyi kullanmayın
  • Göz ardı edilmemesi gereken hatalar için istisnalar kullanın
  • Bir özel durumu yeniden atarken yığın izini temizlemeyin
  • Anlamsal değer eklemeden istisnaları değiştirmekten kaçının
  • İstisnalar [Serileştirilebilir] olarak işaretlenmelidir
  • Şüphe duyduğunuzda İddia etmeyin, bir İstisna oluşturun
  • Her istisna sınıfı en az üç orijinal kurucuya sahip olmalıdır
  • AppDomain.UnhandledException olayını kullanırken dikkatli olun
  • Tekerleği yeniden icat etmeyin
  • Yapılandırılmamış Hata İşlemeyi (VB.Net) kullanmayın

3
Bunu bana biraz daha açıklar mısın? "Kaynağın yokluğunu belirtmek için istisnalar kullanmayın" Bunun arkasındaki nedeni anladığımdan pek emin değilim. Ayrıca sadece bir açıklama: bu cevap "neden" i hiç açıklamıyor. Bunun 5 yaşında olduğunu biliyorum ama yine de beni biraz
Rémi

Başvurulan makalenin bağlantısının süresi doldu. Code Project, makalenin buraya taşınmış olabileceğini öne sürüyor .
DavidRR

15

Windows Forms'un kendi özel durum işleme mekanizmasına sahip olduğunu unutmayın. Formdaki bir düğmeye tıklanırsa ve işleyicisi, işleyicide yakalanmayan bir istisna atarsa, Windows Forms kendi İşlenmeyen İstisna İletişim Kutusunu görüntüler.

İşlenmemiş İstisna İletişim Kutusunun görüntülenmesini önlemek ve bu tür istisnaları günlüğe kaydetme ve / veya kendi hata iletişim pencerenizi sağlamak için önlemek için, Main () yönteminizdeki Application.Run () çağrısından önce Application.ThreadException olayına ekleyebilirsiniz.


Bu öneri için teşekkürler, bunu çok geç öğrendim, sadece linqpad'de doğruladım, beklendiği gibi çalışıyor, temsilci: void Form1_UIThreadException (nesne gönderen, ThreadExceptionEventArgs t) Bu konuyla ilgili bir başka iyi kaynak richnewman.wordpress.com/2007/ 04/08 /… Genel olarak işlenmeyen istisna işleme için: AppDomain.UnhandledException olayı, ana olmayan UI iş parçacığından atılan işlenmemiş istisnalar içindir.
zhaorufei

14

Şimdiye kadar burada yayınlanan tüm tavsiyeler iyi ve dikkate değer.

Genişletmek istediğim bir şey, "Diskte bir dosyanın mevcut olup olmadığı gibi şeyleri önceden test etmeye kıyasla, fırlatılabilecek istisnaların işlenmesi performans düşüşüne neden oluyor mu?"

Temel kural, "dene / yakala blokları pahalıdır." Bu aslında doğru değil. Denemek pahalı değil. Bu, sistemin bir İstisna nesnesi oluşturması ve onu yığın izleme ile yüklemesi gereken, pahalı olan yakalama işlemidir. İstisnanın yeterince istisnai olduğu birçok durum vardır ki, kodu bir dene / yakala bloğuna sarmak mükemmeldir.

Örneğin, bir Sözlüğü dolduruyorsanız, bu:

try
{
   dict.Add(key, value);
}
catch(KeyException)
{
}

genellikle bunu yapmaktan daha hızlıdır:

if (!dict.ContainsKey(key))
{
   dict.Add(key, value);
}

Eklediğiniz her bir öğe için, çünkü istisna yalnızca bir yinelenen anahtar eklediğinizde atılır. (LINQ toplu sorguları bunu yapar.)

Verdiğiniz örnekte, neredeyse hiç düşünmeden dene / yakala kullanırdım. Birincisi, dosyayı kontrol ettiğinizde var olması onu açtığınızda var olacağı anlamına gelmez, bu yüzden yine de istisnayı halletmelisiniz.

İkincisi ve daha da önemlisi, sizin a) süreciniz binlerce dosya açmadıkça ve b) açmaya çalıştığı bir dosyanın mevcut olmaması ihtimali önemsiz derecede düşük değilse, istisna yaratmanın performans düşüşü sizin bir şey değil. hiç fark etmeyeceksiniz. Genel olarak konuşursak, programınız bir dosyayı açmaya çalışırken, yalnızca bir dosyayı açmaya çalışır. Bu, daha güvenli kod yazmanın, mümkün olan en hızlı kodu yazmaktan neredeyse kesinlikle daha iyi olacağı bir durumdur.


3
dict durumunda, şunu yapabilirsiniz: dict[key] = valuebu, daha hızlı değilse de hızlı olmalıdır ..
nawfal

9

İşte takip ettiğim birkaç yönerge

  1. Hatasızlık: Bu daha çok istisna oluşturan bir kılavuzdur.Yaptığınız her varsayım ve bir işleve girdiğiniz her parametre için doğru verilerle başladığınızdan ve varsayımların sizin doğru yapıyorsun. Tipik kontroller arasında argüman boş değil, beklenen aralıkta argüman vb. Bulunur.

  2. Yığın izini koru yeniden atarken - Bu, yeni Exception () atmak yerine basitçe yeniden atarken atmayı kullanmak anlamına gelir. Alternatif olarak, daha fazla bilgi ekleyebileceğinizi düşünüyorsanız, orijinal istisnayı bir iç istisna olarak sarın. Ancak, yalnızca günlüğe kaydetmek için bir istisna yakalıyorsanız, kesinlikle fırlatmayı kullanın;

  3. Başa çıkamayacağınız istisnaları yakalamayın, bu nedenle OutOfMemoryException gibi şeyler hakkında endişelenmeyin çünkü bunlar meydana gelirse zaten pek bir şey yapamazsınız.

  4. Global istisna işleyicileri bağlayın ve mümkün olduğunca fazla bilgi kaydettiğinizden emin olun. Winformlar için hem uygulama alanını hem de işlenmemiş istisna olaylarını bağlayın.

  5. Performans, yalnızca kodu analiz ettiğinizde ve performans darboğazına neden olduğunu gördüğünüzde dikkate alınmalıdır, varsayılan olarak okunabilirlik ve tasarım için optimize edin. Dosyanın varlığını kontrol etmekle ilgili orijinal sorunuza göre, buna bağlı olduğunu söyleyebilirim, Dosyanın orada olmamasıyla ilgili bir şey yapabilirseniz, o zaman evet bunu kontrol edin, aksi takdirde tek yapmanız gereken dosyanın orada değil o zaman noktayı görmüyorum.

  6. Kesinlikle boş yakalama bloklarının gerekli olduğu zamanlar vardır, sanırım birkaç sürümde gelişen kod tabanları üzerinde başka türlü çalışmadığını söyleyen insanlar. Ancak, gerçekten gerekli olduklarından emin olmak için yorumlanmalı ve gözden geçirilmelidirler. En tipik örnek, geliştiricilerin ParseInt () kullanmak yerine dizeyi tam sayıya dönüştürmek için try / catch kullanan geliştiricilerdir.

  7. Kodunuzu arayan kişinin hata durumlarını ele almasını bekliyorsanız, istisnai durumun ne olduğunu detaylandıran ve ilgili bilgileri sağlayan özel istisnalar oluşturun. Aksi takdirde, mümkün olduğunca yerleşik istisna türlerine bağlı kalın.


Hem uygulama etki alanı hem de işlenmemiş iş parçacığı işlenmemiş özel durum işleyicilerini bağlamanın ne faydası var? Yalnızca Appdomain.UnhandledException kullanıyorsanız, her şeyi yakalayacak en genel olan bu değil mi?
Quagmire

Application.ThreadException"İşlenmemiş iş parçacığı istisnası" olayına başvurduğunuzda olayı işlemek mi istediniz ?
Jeff B

4

Özel bağlamımda ne anlama gelirse gelsin, ele almayı düşünmediğim hiçbir şeyi yakalamama felsefesini seviyorum.

Aşağıdakiler gibi kodlar görmekten nefret ediyorum:

try
{
   // some stuff is done here
}
catch
{
}

Bunu zaman zaman gördüm ve istisnai durumlar 'yediğinde' sorun bulmak oldukça zor. Sahip olduğum bir iş arkadaşım bunu yapıyor ve sonunda sürekli bir sorun akışına katkıda bulunma eğiliminde.

Bir istisnaya yanıt olarak belirli sınıfımın yapması gereken bir şey varsa, ancak sorunun olduğu yerde yöntem olarak adlandırılsa da sorunun çözülmesi gerekiyorsa yeniden atarım.

Bence kod proaktif olarak yazılmalıdır ve bu istisnalar, koşulları test etmekten kaçınmak için istisnai durumlar için olmalıdır.


@Kiquenet Üzgünüm biraz belirsizdim. Demek istediğim: Böyle boş yakalamalar yapmayın, bunun yerine Dispatcher.UnhandledException'a bir işleyici ekleyin ve en azından bir günlük ekleyin, böylece ekmek kırıntıları olmadan yenmesin :) Ancak sessiz bir bileşen gereksiniminiz yoksa her zaman istisnalar eklemelisiniz tasarımınıza. Atılmaları gerektiğinde onları atın, sizin için Arabirimler / API / herhangi bir Sınıf için net sözleşmeler yapın.
LuckyLikey

4

Sadece çıkıyorum ama size istisna işlemeyi nerede kullanacağınız konusunda kısa bir bilgi vereceğim. Döndüğümde diğer noktalarınıza da değinmeye çalışacağım :)

  1. Bilinen tüm hata koşullarını açıkça kontrol edin *
  2. Tüm vakaların üstesinden gelip gelemeyeceğinizden emin değilseniz, kodun etrafına bir dene / yakala ekleyin
  3. Çağırdığınız .NET arabirimi bir istisna atarsa, kodun etrafına bir dene / yakala ekleyin
  4. Sizin için karmaşıklık eşiğini geçerse, kodun çevresine bir dene / yakala ekleyin
  5. Akıl sağlığı kontrolü için kodun etrafına bir dene / yakala ekleyin: BU HİÇBİR ZAMAN OLMAMALIDIR diyorsunuz
  6. Genel bir kural olarak, dönüş kodlarının yerine istisnaları kullanmıyorum. Bu .NET için iyi, ama ben değil. Yine de bu kuralın istisnaları var (hehe), üzerinde çalıştığınız uygulamanın mimarisine de bağlı.

* Sebep dahilinde. Bir kozmik ışının verilerinize çarpıp birkaç bitin ters dönmesine neden olup olmadığını kontrol etmeye gerek yoktur. "Makul" olanı anlamak, bir mühendis için kazanılmış bir beceridir. Ölçmek zor, ancak sezilmesi kolay. Yani, herhangi bir örnekte neden bir dene / yakala kullandığımı kolayca açıklayabilirim, ancak yine de aynı bilgiyi başka birine aşılamakta zorlanıyorum.

Ben özellikle istisnalara dayalı mimarilerden uzaklaşma eğilimindeyim. try / catch, bu şekilde bir performans isabetine sahip değildir, isabet, istisna atıldığında gelir ve kod, bir şey onu işlemeden önce çağrı yığınının birkaç düzeyini yükseltmek zorunda kalabilir.


4

Bağlı kalmaya çalışan altın kural, istisnayı kaynağa mümkün olduğunca yakın ele almaktır.

Bir istisnayı yeniden atmanız gerekiyorsa, buna eklemeyi deneyin, bir FileNotFoundException'ı yeniden atmak çok yardımcı olmaz, ancak bir ConfigurationFileNotFoundException atılması, zincirin herhangi bir yerinde yakalanmasına ve harekete geçmesine izin verir.

İzlemeye çalıştığım diğer bir kural, dene / yakala'yı bir program akışı biçimi olarak kullanmamaktır, bu yüzden dosyaları / bağlantıları doğruluyorum, nesnelerin başlatıldığından emin oluyorum, vb. Onları kullanmadan önce. Dene / yakala, İstisnalar, kontrol edemeyeceğiniz şeyler için olmalıdır.

Boş bir catch bloğuna gelince, istisnayı oluşturan kodda önemli bir şey yapıyorsanız, istisnayı minimumda yeniden atmalısınız. Çalıştırmayan istisnayı atan kodun hiçbir sonucu yoksa neden ilk etapta yazdınız?


Bu "altın kural", en iyi ihtimalle keyfidir.
Evan Harper

3

ThreadException olayını yakalayabilirsiniz.

  1. Solution Explorer'da bir Windows Uygulama projesi seçin.

  2. Oluşturulan Program.cs dosyasını üzerine çift tıklayarak açın.

  3. Aşağıdaki kod satırını kod dosyasının üstüne ekleyin:

    using System.Threading;
  4. Main () yönteminde, yöntemin ilk satırı olarak aşağıdakileri ekleyin:

    Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
  5. Main () yönteminin altına aşağıdakileri ekleyin:

    static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
    {
        // Do logging or whatever here
        Application.Exit();
    }
  6. Olay işleyicideki işlenmeyen istisnayı işlemek için kod ekleyin. Uygulamada başka hiçbir yerde ele alınmayan herhangi bir istisna, yukarıdaki kodla ele alınır. En yaygın olarak, bu kod hatayı kaydetmeli ve kullanıcıya bir mesaj göstermelidir.

referans: https://blogs.msmvps.com/deborahk/global-exception-handler-winforms/


@Kiquenet üzgünüm, VB hakkında bilmiyorum
Omid-RH

2

İstisnalar pahalıdır ancak gereklidir. Her şeyi bir deneme yakalamaya bağlamanız gerekmez, ancak istisnaların her zaman eninde sonunda yakalanmasını sağlamanız gerekir. Çoğu tasarımınıza bağlı olacaktır.

İstisnanın yükselmesine izin vermek de aynısını yapacaksa yeniden atmayın. Hataların fark edilmeden geçmesine asla izin vermeyin.

misal:

void Main()
{
  try {
    DoStuff();
  }
  catch(Exception ex) {
    LogStuff(ex.ToString());
  }

void DoStuff() {
... Stuff ...
}

DoStuff yanlış giderse, yine de kurtarılmasını isteyeceksiniz. İstisna, main'e fırlatılacak ve olayların trenini ex'in yığın izinde göreceksiniz.


1

Bir istisnayı ne zaman yeniden atmalıyım?

Her yerde, ancak son kullanıcı yöntemleri ... düğme tıklama işleyicileri gibi

Bir tür merkezi hata işleme mekanizmasına sahip olmaya çalışmalı mıyım?

Bir günlük dosyası yazıyorum ... WinForm uygulaması için oldukça kolay

Diskte bir dosyanın mevcut olup olmadığı gibi şeyleri önceden test etmekle karşılaştırıldığında, fırlatılabilecek istisnaların işlenmesi performans düşüşüne neden oluyor mu?

Bundan emin değilim, ancak istisnaları aşmanın iyi bir uygulama olduğuna inanıyorum ... Demek istediğim, bir dosyanın var olup olmadığını ve bir FileNotFoundException oluşturup oluşturmadığını sorabilirsiniz.

Tüm yürütülebilir kodlar, dene-yakala bloklarının içine alınmalı mı?

yeap

Boş bir yakalama bloğunun kabul edilebilir olabileceği zamanlar var mı?

Evet, bir tarih göstermek istediğinizi varsayalım, ancak bu tarihin nasıl saklandığına dair hiçbir fikriniz yok (gg / aa / yyyy, aa / gg / yyyy, vb.), Tp ayrıştırmayı deneyin, ancak başarısız olursa devam edin .. . senin için alakasızsa ... evet derdim, var


1

Çok çabuk öğrendiğim tek şey, programımın akışı dışındaki herhangi bir şeyle (yani Dosya Sistemi, Veritabanı Çağrıları, Kullanıcı Girdisi) etkileşime giren her kod parçasını mutlaka deneme-yakalama bloklarıyla kaplamaktı. Try-catch bir performans düşüşüne neden olabilir, ancak genellikle kodunuzun bu yerlerinde fark edilmez ve güvenli bir şekilde kendini amorti eder. Kullanıcının gerçekten "yanlış" olmayan bir şey yapabileceği yerlerde boş yakalama blokları kullandım, ancak bir istisna atabilir ... Kullanıcı gri yer tutucuyu DoubleCLicks ise akla gelen bir örnek GridView'dadır. Sol üstteki hücre, CellDoubleClick olayını tetikler, ancak hücre bir satıra ait değildir. Bu durumda sen

yapmazsın gerçekten bir mesaj göndermeniz gerekiyor, ancak onu yakalamazsanız, kullanıcıya işlenmemiş bir istisna hatası atacaktır.


1

Bir istisnayı yeniden atarken anahtar kelime kendisi tarafından atılır. Bu, yakalanan istisnayı atacak ve yine de nereden geldiğini görmek için yığın izlemeyi kullanabilecektir.

Try
{
int a = 10 / 0;
}
catch(exception e){
//error logging
throw;
}

bunu yapmak yığın izlemenin catch deyiminde bitmesine neden olur. (bundan kaçının)

catch(Exception e)
// logging
throw e;
}

Bu hala .NET Framework ve .NET Core'un en son sürümleri için geçerli mi?
LuckyLikey

1

n benim deneyimlerim, onları yaratacağımı bildiğimde istisnaları yakalamaya uygun gördüm. Bir web uygulamasında olduğum ve bir Response.Redirect yaptığım durumlar için, bir System.ThreadAbortException alacağımı biliyorum. Kasıtlı olduğu için, sadece belirli tip için bir yakalamaya sahibim ve sadece yutuyorum.

try
{
/*Doing stuff that may cause an exception*/
Response.Redirect("http:\\www.somewhereelse.com");
}
catch (ThreadAbortException tex){/*Ignore*/}
catch (Exception ex){/*HandleException*/}

1

Kuralına derinden katılıyorum:

  • Hataların fark edilmeden geçmesine asla izin vermeyin.

Nedeni şudur:

  • Kodu ilk kez yazdığınızda, büyük olasılıkla 3-parti kod, .NET FCL lirary veya iş arkadaşlarınızın en son katkıları hakkında tam bilgiye sahip olmayacaksınız. Gerçekte, her istisna olasılığını iyi bilene kadar kod yazmayı reddedemezsiniz. Yani
  • Kendimi bilinmeyen şeylerden korumak istediğim için dene / yakala (İstisna istisnası) kullandığımı ve fark ettiğiniz gibi OutOfMemoryException vb. Gibi daha spesifik olanları değil Exception'ı yakaladığımı sürekli olarak görüyorum. Ve her zaman istisna yapıyorum ForceAssert.AlwaysAssert (false, ex.ToString ()) tarafından bana (veya QA'ya) açılır;

ForceAssert.AlwaysAssert, DEBUG / TRACE makrosunun tanımlı olup olmadığına bakılmaksızın benim kişisel Trace.Assert yöntemimdir.

Geliştirme döngüsü belki: Çirkin Assert diyaloğunu fark ettim veya bir başkası bana bundan şikayet etti, sonra koda geri dönüp istisnayı ortaya çıkarmanın nedenini bulup nasıl işleyeceğime karar verdim.

Bu arada ben yazabiliriz MY kısa sürede kodu ve bilinmeyen etki alanından beni korudu, ama her zaman anormal şeyler sistem güvenli ve daha güvenlik var bu arada, olmamış fark edilmeden.

Birçoğunuzun benimle aynı fikirde olmayacağınızı biliyorum çünkü bir geliştirici kodunun her ayrıntısını bilmeli, açıkçası ben de eski günlerde bir püristim. Ama bugünlerde yukarıdaki politikanın daha pragmatik olduğunu öğrendim.

WinForms kodu için her zaman uyduğum altın kural şudur:

  • Her zaman olay işleyici kodunuzu deneyin / yakalayın (İstisna)

bu, kullanıcı arayüzünüzün her zaman kullanılabilir olmasını koruyacaktır.

Performans isabeti için, performans cezası yalnızca kod yakalamaya ulaştığında gerçekleşir, gerçek istisna olmadan çalıştırmanın önemli bir etkisi yoktur.

İstisna çok az şansla gerçekleşmelidir, aksi takdirde istisna değildir.


-1

Kullanıcı hakkında düşünmelisiniz. Uygulama çökmesi, sonkullanıcının istediği şey. Bu nedenle, başarısız olabilecek herhangi bir işlemin ui düzeyinde bir deneme yakalama bloğuna sahip olması gerekir. Her yöntemde try catch kullanmak gerekli değildir, ancak kullanıcı bir şeyi her yaptığında genel istisnaları ele alabilmelidir. Bu, hiçbir şekilde sizi ilk durumda istisnaları önlemek için her şeyi kontrol etmekten kurtarmaz, ancak hatasız karmaşık bir uygulama yoktur ve işletim sistemi beklenmedik sorunları kolayca ekleyebilir, bu nedenle beklenmeyeni önceden tahmin etmeli ve bir kullanıcının kullanmak isteyip istemediğinden emin olmalısınız. uygulama çöktüğü için işlem veri kaybı olmayacak. Uygulamanızın çökmesine asla izin vermenize gerek yoktur, eğer istisnaları yakalarsanız, hiçbir zaman belirsiz bir durumda olmayacaktır ve kullanıcı DAİMA bir çökmeden rahatsız olur. İstisna en üst düzeyde olsa bile, kilitlenmemesi, kullanıcının istisnayı hızla yeniden oluşturabileceği veya en azından hata mesajını kaydedebileceği ve bu nedenle sorunu çözmenize büyük ölçüde yardımcı olabileceği anlamına gelir. Kesinlikle basit bir hata mesajı almaktan ve ardından yalnızca Windows hata iletişim kutusunu veya buna benzer bir şeyi görmekten çok daha fazlası.

Bu yüzden ASLA kibirli olmalısın ve uygulamanızda hiçbir hata olmadığını düşünmemelisiniz, bu garanti edilmez. Ve uygun kodla ilgili bazı try catch bloklarını sarmak ve bir hata mesajı göstermek / hatayı günlüğe kaydetmek çok küçük bir çabadır.

Bir kullanıcı olarak, bir tarayıcı veya ofis uygulaması ya da her ne olursa olsun çöktüğünde kesinlikle ciddi şekilde sinirleniyorum. İstisna, uygulama devam edemeyecek kadar yüksekse, bu mesajı görüntülemek ve kullanıcıya ne yapması gerektiğini söylemek (yeniden başlatmak, bazı işletim sistemi ayarlarını düzeltmek, hatayı bildirmek, vb.) Basitçe çökmekten daha iyidir ve bu kadar.


Cevapları bir rant gibi daha az yazmaya çalışıp bunun yerine daha spesifik olmaya ve amacınızı kanıtlamaya çalışabilir misiniz? Ayrıca Nasıl Cevaplanır'a bir göz atın .
LuckyLikey
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.