.NET'te geçersiz veya beklenmeyen parametreler için hangi özel durumlar atılmalıdır?


163

.NET'te geçersiz veya beklenmeyen parametreler için ne tür özel durumlar atılmalıdır? Birini ne zaman diğeri yerine seçerim?

Takip et:

Bir aya karşılık gelen bir tamsayı bekleyen bir işleve sahipseniz ve '42'de geçtiyseniz, hangi istisnayı kullanırsınız? Bu bir koleksiyon olmasa da "kapsam dışı" kategorisine girer mi?

Yanıtlar:


249

: Ben kullanım ister ArgumentException, ArgumentNullExceptionve ArgumentOutOfRangeException.

Argümanın kendisine çok fazla odaklanmayan, ancak çağrıyı bir bütün olarak yargılayan başka seçenekler de var:

  • InvalidOperationException- Bağımsız değişken OK olabilir, ancak nesnenin geçerli durumunda olmayabilir. Kredi STW'ye (önceden Yoooder) gidiyor. Oy cevabını yanı yukarı.
  • NotSupportedException- Aktarılan argümanlar geçerli, ancak bu uygulamada desteklenmiyor. Bir FTP istemcisi düşünün ve istemcinin desteklemediği bir komut iletin.

İşin püf noktası, yöntemin neden bu şekilde adlandırılamayacağını en iyi ifade eden istisnayı atmaktır. İdeal olarak, istisna neyin yanlış gittiğini, niçin yanlış olduğu ve nasıl düzeltileceği hakkında ayrıntılı olmalıdır.

Hata mesajları yardıma, belgelere veya diğer kaynaklara işaret ettiğinde seviyorum. Örneğin, Microsoft, KB makaleleriyle iyi bir ilk adım attı, örneğin “Internet Explorer'da bir Web sayfasını ziyaret ettiğimde neden" İşlem iptal edildi "hata iletisini alıyorum?" . Hatayla karşılaştığınızda, hata iletisindeki KB makalesine yönlendirirsiniz. İyi yapmadığı şey size söylemedikleri, neden özellikle başarısız olduğu.

Yorumlar için STW (eski Yoooder) tekrar teşekkürler.


İzleminize yanıt olarak, bir ArgumentOutOfRangeException. MSDN'nin bu istisna hakkında ne söylediğine bakın:

ArgumentOutOfRangeExceptionbir yöntem çağrıldığında ve yönteme iletilen bağımsız değişkenlerden en az biri null başvuru ( NothingVisual Basic'te) olmadığında ve geçerli bir değer içermediğinde atılır .

Dolayısıyla, bu durumda, bir değer geçiriyorsunuz, ancak aralığınız 1–12 olduğundan geçerli bir değer değil. Bununla birlikte, bunu belgeleme şekliniz, API'nızın ne attığını netleştirir. Çünkü söylesem de ArgumentOutOfRangeException, başka bir geliştirici söyleyebilir ArgumentException. Kolaylaştırın ve davranışı belgeleyin.


Hatırlatma! Onun özel sorusunu tam olarak doğru cevapladığınızı kabul ediyorum, ancak savunma kodlama ve parametreleri doğrulamaya yardımcı olmak için aşağıdaki cevabımı görün;
STW

+1 ancak istisna atıldığını ve neden 'doğru' olanı seçmekten daha önemli olduğunu belgeler.
pipTheGeek

@pipTheGeek - Bence bu gerçekten tartışma konusu. Belgeleme kesinlikle önemli olmakla birlikte, tüketen geliştiricinin proaktif veya savunmacı olmasını ve belgeleri ayrıntılı olarak okumasını beklemektedir. Son kullanıcı bunlardan birini değil diğerini görme şansına sahip olduğu için iyi belgeler üzerinde dostça / açıklayıcı bir hata tercih ederim; bir son kullanıcının kötü bir programcıya açıklayıcı bir hata iletmesini, kötü bir programcıya tüm dokümanları okuyabileceğinden daha iyi bir şansı vardır
STW

4
ArgumentException'ı yakalarsanız, ArgumentOutOfRange öğesini de yakalayacağını unutmayın.
Steven Evers

Nasıl olur FormatException: Bağımsız değişkenin biçimi geçersiz olduğunda veya bileşik biçim dizesi iyi biçimlendirilmediğinde atılan özel durum.
Anthony

44

Josh'un cevabına oy verdim , ancak listeye bir tane daha eklemek istiyorum:

Bağımsız değişken geçerliyse, System.InvalidOperationException oluşturulmalıdır, ancak nesne, bağımsız değişkenin kullanılmaması gereken bir durumdadır.

MSDN'den Alınan Güncelleme :

InvalidOperationException, yöntem çağırma başarısızlığının geçersiz bağımsız değişkenler dışındaki nedenlerden kaynaklandığı durumlarda kullanılır.

Diyelim ki nesnenizde PerformAction (enmSomeAction eylemi) yöntemi var, geçerli enmSomeActions Açık ve Kapalı. PerformAction (enmSomeAction.Open) öğesini arka arkaya iki kez çağırırsanız, ikinci çağrı InvalidOperationException özel durumunu (argüman geçerli olduğu için, ancak denetimin geçerli durumu için değil) atmalıdır.

Zaten defansif olarak programlayarak doğru olanı yaptığınızdan, ObjectDisposedException'dan bahsetmem gereken bir istisna daha var. Eğer senin nesne uygular sonra ıdisposable her zaman elden çıkarılan durumunu izleme Bir sınıf değişkeni sahip olmalıdır; nesneniz atılmışsa ve üzerinde bir yöntem çağrılmışsa, ObjectDisposedException öğesini yükseltmelisiniz:

public void SomeMethod()
{
    If (m_Disposed) {
          throw new ObjectDisposedException("Object has been disposed")
     }
    // ... Normal execution code
}

Güncelleme: İzleminizi cevaplamak için: Bu, belirsiz bir durumdur ve belirli bir veri kümesini temsil etmek için kullanılan genel (.NET Generics anlamda değil) veri türü tarafından biraz daha karmaşık hale getirilmiştir; bir enum veya diğer güçlü bir şekilde yazılmış bir nesne daha ideal bir uyum olacaktır - ancak her zaman bu kontrole sahip değiliz.

Şahsen ArgumentOutOfRangeException doğru yalın ve geçerli değerleri 1-12 olduğunu gösteren bir ileti sağlar. Benim gerekçem aylar hakkında konuştuğunuzda, ayların tamsayı temsillerinin geçerli olduğunu varsayarak, 1-12 aralığında bir değer beklediğinizdir. Sadece belirli aylar (31 güne sahip aylar gibi) geçerli olsaydı, o zaman aralık başına bir aralıkla uğraşmazsınız ve geçerli değerleri belirten genel bir ArgumentException atardım ve bunları yöntemin yorumlarında da belgeleyeceğim.


1
İyi bir nokta. Bu, geçersiz ve beklenmeyen girdi arasındaki farkı açıklayabilir. +1
Daniel Brückner

Psst, seninle aynı fikirdeyim senin gök gürültüsünü çalmayacaksın. Ama işaret ettiğinden beri cevabımı güncelledim
JoshBerke

38

Gerçek değere ve hangi istisnanın en uygun olduğuna bağlı olarak:

Bu yeterince kesin değilse, kendi istisna sınıfınızı türetmeniz yeterlidir ArgumentException.

Yoooder'in cevabı beni aydınlatıyordu. Bir girdidir geçersiz bir giriş iken o, her an geçerli değilse beklenmedik bu sistemin mevcut durumu için geçerli değilse. Yani sonraki durumda an InvalidOperationExceptionmakul bir seçimdir.


6
MSDN'nin InvalidOperationException sayfasından alınmıştır: "InvalidOperationException, bir yöntemin çağrılmamasının geçersiz argümanlar dışındaki nedenlerden kaynaklandığı durumlarda kullanılır."
STW


3

ArgumentException :

Bir yöntem çağrıldığında ve iletilen bağımsız değişkenlerden en az biri çağrılan yöntemin parametre belirtimini karşılamadığında ArgumentException oluşturulur. Tüm ArgumentException örnekleri, geçersiz bağımsız değişkeni ve bağımsız değişken için beklenen değer aralığını açıklayan anlamlı bir hata iletisi taşımalıdır.

Belirli geçersizlik türleri için de birkaç alt sınıf mevcuttur. Bağlantının alt türlerin özetleri ve ne zaman uygulanmaları gerektiği vardır.


1

Kısa cevap:
İkisi de

Daha uzun cevap:
Argument * Exception'ı kullanma (bileşen kitaplığı gibi üzerinde bulunan bir ürün olan bir kitaplık hariç) bir koku. İstisnalar, kullanıcının (yani API tüketicisi) eksikliklerini değil, hataları değil istisnai durumları ele almak içindir.

En uzun yanıt:
Bir kitaplık yazmadığınız sürece geçersiz bağımsız değişkenler için istisnalar atmak kaba olur.
İki (veya daha fazla) nedenden dolayı iddiaları kullanmayı tercih ediyorum:

  • İddiaların test edilmesine gerek yoktur, ancak atma iddiaları yapar ve ArgumentNullException'a karşı test gülünç görünür (deneyin).
  • İddialar, birimin amaçlanan kullanımını daha iyi iletir ve yürütülebilir bir sınıflamaya, sınıf davranışı belirtiminden daha yakındır.
  • Onaylama ihlali davranışını değiştirebilirsiniz. Örneğin hata ayıklama derlemesinde bir mesaj kutusu iyidir, böylece KG'niz size hemen onunla vurur (IDE'nizin gerçekleştiği satırda kesilmesini sağlar), birim testinde onaylama hatasını bir test hatası olarak gösterebilirsiniz. .

Null istisnasının işlenmesi şöyle görünür (alaycı, açıkçası):

try {
    library.Method(null);
}
catch (ArgumentNullException e) {
    // retry with real argument this time
    library.Method(realArgument);
}

Durum beklendiği halde istisnai olduğunda istisnalar kullanılır (IO arızası gibi tüketicinin kontrolü dışında olan şeyler olur). Argüman * İstisna bir hatanın göstergesidir ve (benim görüşüm) testlerle ele alınacak ve Debug ile desteklenecektir.

BTW: Bu özel durumda, int yerine Month türünü kullanabilirsiniz. Tip güvenliği (Aspect # rulez!) Söz konusu olduğunda C # kısalır, ancak bazen bu hataları hep birlikte önleyebilir (veya derleme zamanında yakalayabilirsiniz).

Ve evet, MicroSoft bu konuda yanlış.


6
IMHO, çağrılan yöntem makul bir şekilde devam edemediğinde istisnalar da atılmalıdır. Bu, arayanın sahte argümanları geçtiği durumu içerir. Bunun yerine ne yapardınız? -1 dönüş?
John Saunders

1
Geçersiz bağımsız değişkenler bir iç işlevin başarısız olmasına neden olursa, iç işlevden bir InvalidArgumentException özelliğinin yakalanması ve daha bilgilendirici bir işlevle tamamlanması yerine, geçerlilik için bağımsız değişkenlerin test edilmesinin artıları ve eksileri nelerdir? İkinci yaklaşım, ortak durumda performansı artırıyor gibi görünebilir, ancak bunun çok fazla yapıldığını görmedim.
supercat

Bu soru etrafında yapılan hızlı bir Google araması, Genel İstisnayı atmanın herkesin en kötü uygulaması olduğunu gösterir. Argümanın iddiasıyla ilgili olarak, bu konuda küçük kişisel projelerde değer görüyorum, ancak geçersiz argümanların büyük olasılıkla uygulamanın kötü yapılandırılması veya kötü anlaşılması nedeniyle olduğu kurumsal uygulamalarda değil.
Maksimum

0

Kullanabileceğiniz standart bir ArgumentException var veya alt sınıfınızı oluşturabilir ve kendinizinkini oluşturabilirsiniz. Birkaç özel ArgumentException sınıfı vardır:

http://msdn.microsoft.com/en-us/library/system.argumentexception(VS.71).aspx

Hangisi en iyi çalışırsa.


1
Neredeyse tüm davalara katılmıyorum; sağlanan .NET Bağımsız Değişken * İstisna sınıfları çok yaygın olarak kullanılır ve sorunu tüketiciye bildirmek için yeterli belirli bilgileri sağlama olanağı sağlar.
STW

Açıklığa kavuşturmak için - Argüman * İstisna sınıflarından türeyen hemen hemen tüm davalar için katılmıyorum. .NET Bağımsız Değişken Özel Durumlarından birini ve açıklayıcı ve açık bir iletiyi kullanmak, bağımsız değişkenlerin geçersiz olduğu her durum için az çok yeterli ayrıntı sağlar.
STW

kabul etti, ama sadece mevcut seçenekleri tarif ediyordum. "Tercih edilen" yöntem konusunda kesinlikle daha açık olmalıydım.
Scott M.20
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.