.NET में अमान्य या अनपेक्षित मापदंडों के लिए क्या अपवाद फेंके जाने चाहिए?


163

.NET में अमान्य या अप्रत्याशित पैरामीटर के लिए किस प्रकार के अपवादों को फेंक दिया जाना चाहिए? मैं एक के बजाय दूसरे को कब चुनूंगा?

ऊपर का पालन करें:

यदि आपके पास एक फ़ंक्शन एक महीने के लिए एक पूर्णांक की अपेक्षा करता है और आप '42' में पारित हुए तो आप किस अपवाद का उपयोग करेंगे? क्या यह "आउट ऑफ़ रेंज" श्रेणी में आएगा, हालांकि यह एक संग्रह नहीं है?

जवाबों:


249

मैं उपयोग करना चाहते: ArgumentException, ArgumentNullException, और ArgumentOutOfRangeException

  • ArgumentException - तर्क में कुछ गड़बड़ है।
  • ArgumentNullException - तर्क अशक्त है।
  • ArgumentOutOfRangeException - मैं इसका एक बहुत उपयोग नहीं करता हूं, लेकिन एक आम उपयोग एक संग्रह में अनुक्रमण कर रहा है, और एक सूचकांक दे रहा है जो बड़े पैमाने पर है।

अन्य विकल्प भी हैं, जो केवल तर्क पर इतना ध्यान केंद्रित नहीं करते हैं, बल्कि संपूर्ण रूप से कॉल का न्याय करते हैं:

  • InvalidOperationException- तर्क ठीक हो सकता है, लेकिन वस्तु की वर्तमान स्थिति में नहीं। इसका श्रेय STW (पहले के Yoooder) को जाता है। उसके उत्तर को भी वोट दें ।
  • NotSupportedException- पारित किए गए तर्क मान्य हैं, लेकिन इस कार्यान्वयन में बस समर्थित नहीं हैं। एक एफ़टीपी क्लाइंट की कल्पना करें, और आप एक कमांड पास करते हैं जिसमें क्लाइंट सपोर्ट नहीं करता है।

चाल उस अपवाद को फेंकने के लिए है जो सबसे अच्छा व्यक्त करता है कि विधि को जिस तरह से नहीं कहा जा सकता है। आदर्श रूप से, अपवाद इस बारे में विस्तृत होना चाहिए कि क्या गलत हुआ, क्यों गलत है, और इसे कैसे ठीक किया जाए।

मैं प्यार करता हूँ जब त्रुटि संदेश मदद, प्रलेखन, या अन्य संसाधनों को इंगित करता है। उदाहरण के लिए, Microsoft ने अपने KB लेखों के साथ एक अच्छा पहला कदम उठाया, उदाहरण के लिए "जब मैं इंटरनेट एक्सप्लोरर में एक वेब पेज पर जाता हूं तो मुझे" ऑपरेशन निरस्त "त्रुटि संदेश क्यों मिलता है?" । जब आप त्रुटि का सामना करते हैं, तो वे आपको त्रुटि संदेश में KB आलेख की ओर इशारा करते हैं। वे जो अच्छा नहीं करते हैं वह यह है कि वे आपको नहीं बताते हैं कि विशेष रूप से यह विफल क्यों हुआ।

टिप्पणी के लिए फिर से STW (पूर्व Yoooder) के लिए धन्यवाद।


आपके फॉलोअप के जवाब में, मैं एक फेंक दूंगा ArgumentOutOfRangeException। इस अपवाद के बारे में MSDN क्या कहता है, इसे देखें:

ArgumentOutOfRangeExceptionफेंक दिया जाता है जब एक विधि लागू होती है और विधि को पारित किए गए कम से कम एक तर्क शून्य संदर्भ ( Nothingविज़ुअल बेसिक में) नहीं होता है और इसमें एक वैध मूल्य नहीं होता है।

तो, इस मामले में, आप एक मान पास कर रहे हैं, लेकिन यह मान्य मान नहीं है, क्योंकि आपकी सीमा 1-12 है। हालाँकि, जिस तरह से आप इसे दस्तावेज़ करते हैं, यह स्पष्ट करता है कि आपका एपीआई क्या फेंकता है। क्योंकि मैं कह सकता हूं ArgumentOutOfRangeException, एक और डेवलपर कह सकता है ArgumentException। इसे आसान बनाएं और व्यवहार का दस्तावेजीकरण करें।


श्श्श! मैं सहमत हूं कि आपने उनके विशिष्ट प्रश्न का बिल्कुल सही उत्तर दिया, लेकिन रक्षात्मक कोडिंग और मान्य मापदंडों को पूरा करने में मदद करने के लिए नीचे दिए गए मेरे उत्तर को देखें; --D
STW

+1 लेकिन यह निर्दिष्ट करना कि क्या अपवाद फेंका गया है और 'सही' को चुनने से अधिक महत्वपूर्ण क्यों है।
pipTheGeek

@pipTheGeek - मुझे लगता है कि यह वास्तव में एक लूट बिंदु है। जबकि दस्तावेज निश्चित रूप से महत्वपूर्ण है, यह भी उपभोग्य डेवलपर को सक्रिय या रक्षात्मक होने और वास्तव में प्रलेखन को विस्तार से पढ़ने की उम्मीद करता है। मैं अच्छे प्रलेखन पर एक दोस्ताना / वर्णनात्मक त्रुटि के लिए विकल्प चुनूंगा क्योंकि अंत-उपयोगकर्ता के पास उनमें से एक को देखने का मौका है और दूसरे को नहीं; एंड-यूज़र होने का एक बेहतर मौका है कि एक गरीब प्रोग्रामर को एक खराब प्रोग्रामर से संवाद करने में कोई त्रुटि हो, जो पूरा डॉक्स पढ़ने वाले एक गरीब प्रोग्रामर की तुलना में है
STW

4
ध्यान दें, यदि आप ArgumentException को पकड़ते हैं, तो यह ArgumentOutOfRange भी पकड़ लेगा।
स्टीवन एवर्स

कैसे के बारे में FormatException: एक अपवाद का तर्क अमान्य होने पर, या जब एक समग्र प्रारूप स्ट्रिंग अच्छी तरह से नहीं बनाया जाता है, तो वह अपवाद।
एंथनी

44

मैंने जोश के जवाब के लिए मतदान किया , लेकिन सूची में एक और जोड़ना चाहेंगे:

यदि तर्क मान्य है, तो System.InvalidOperationException को फेंक दिया जाना चाहिए, लेकिन ऑब्जेक्ट उस स्थिति में है जहां तर्क का उपयोग नहीं किया जाना चाहिए।

MSDN से अपडेट किया गया:

InvalidOperationException का उपयोग उन मामलों में किया जाता है जब विधि को लागू करने में विफलता अमान्य तर्कों के अलावा अन्य कारणों से होती है।

मान लीजिए कि आपकी ऑब्जेक्ट में एक PerformAction (enmSomeAction क्रिया) विधि है, मान्य enmSomeActions खुले और बंद हैं। यदि आप एक पंक्ति में दो बार PerformAction (enmSomeAction.Open) को कॉल करते हैं, तो दूसरी कॉल को InvalidOperationException को फेंक देना चाहिए (चूंकि नियंत्रण वैध था, लेकिन नियंत्रण की वर्तमान स्थिति के लिए नहीं)

चूंकि आप पहले से ही रक्षात्मक रूप से प्रोग्रामिंग करके सही काम कर रहे हैं इसलिए मेरे पास एक अन्य अपवाद है जिसका उल्लेख है ObjectDisposedException। यदि आपकी वस्तु आईडीसिसोपयोगी है, तो आपके पास हमेशा एक वैरिएबल वैरिएबल होना चाहिए जो कि डिस्पोजल स्थिति पर नज़र रखता हो; यदि आपकी वस्तु का निपटान हो गया है और एक विधि उस पर कॉल की जाती है, तो आपको ObjectDisposedException को उठाना चाहिए:

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

अद्यतन: अपने अनुवर्ती का जवाब देने के लिए: यह एक अस्पष्ट स्थिति का एक सा है, और एक सामान्य (.NET Generics अर्थ में नहीं) डेटा के एक विशिष्ट सेट का प्रतिनिधित्व करने के लिए इस्तेमाल किया जा रहा द्वारा थोड़ा और अधिक जटिल बना दिया गया है; एक एनम या अन्य दृढ़ता से टाइप की गई वस्तु एक अधिक आदर्श फिट होगी - लेकिन हमारे पास हमेशा यह नियंत्रण नहीं होता है।

मैं व्यक्तिगत रूप से ArgumentOutOfRangeException की ओर झुकूंगा और एक संदेश प्रदान करूंगा जो मान्य मानों को दर्शाता है 1-12। मेरा तर्क यह है कि जब आप महीनों के बारे में बात करते हैं, तो यह मानते हुए कि महीनों के सभी पूर्णांक निरूपण मान्य हैं, तब आप 1-12 की सीमा में मूल्य की उम्मीद कर रहे हैं। यदि केवल कुछ महीने (जैसे महीने जिसमें 31 दिन थे) वैध थे, तो आप एक सीमा-प्रति के साथ काम नहीं करेंगे और मैं एक सामान्य तर्क को फेंक दूंगा, जो वैध मूल्यों को इंगित करता है, और मैं उन्हें विधि की टिप्पणियों में भी दस्तावेज करूंगा।


1
अच्छी बात। यह अमान्य और अस्पष्टीकृत इनपुट के बीच अंतर की व्याख्या कर सकता है। +1
डेनियल ब्रुकनर

Psst, मैं आपसे सहमत हूँ बस आपकी गड़गड़ाहट चोरी करने के लिए नहीं थी। लेकिन जब से आपने इसे इंगित किया है, मैंने अपना जवाब अपडेट किया
जोशबर्के

38

वास्तविक मूल्य पर निर्भर करता है और क्या अपवाद सबसे अच्छा फिट बैठता है:

  • ArgumentException (मूल्य के साथ कुछ गलत है)

  • ArgumentNullException (तर्क शून्य है जबकि इसकी अनुमति नहीं है)

  • ArgumentOutOfRangeException (तर्क में मान्य श्रेणी के बाहर का मान है)

यदि यह पर्याप्त सटीक नहीं है, तो बस अपने अपवाद वर्ग से प्राप्त करें ArgumentException

योडर के जवाब ने मुझे मंत्रमुग्ध कर दिया। एक इनपुट अमान्य है अगर यह किसी भी समय मान्य नहीं है, जबकि एक इनपुट अप्रत्याशित है अगर यह सिस्टम की वर्तमान स्थिति के लिए मान्य नहीं है। तो बाद के मामले InvalidOperationExceptionमें एक उचित विकल्प है।


6
InvalidOperationException पर MSDN के पृष्ठ से लिया गया: "InvalidOperationException का उपयोग उन मामलों में किया जाता है जब विधि को लागू करने में विफलता अमान्य तर्कों के अलावा अन्य कारणों से होती है।"
STW


3

तर्कबोध :

ArgumentException को तब फेंका जाता है जब किसी विधि को लागू किया जाता है और कम से कम एक पास की गई तर्कों को विधि के पैरामीटर विनिर्देश को पूरा नहीं करता है। तर्क-वितर्क के सभी उदाहरणों में अमान्य तर्क के साथ-साथ तर्क के लिए मूल्यों की अपेक्षित सीमा का वर्णन करते हुए एक सार्थक त्रुटि संदेश होना चाहिए।

विशिष्ट प्रकार की अमान्यता के लिए कुछ उपवर्ग भी मौजूद हैं। लिंक में उपप्रकारों का सारांश है और जब उन्हें आवेदन करना चाहिए।


1

संक्षिप्त उत्तर:
न तो

लंबे समय तक उत्तर:
तर्क * अपवाद का उपयोग करना (एक पुस्तकालय को छोड़कर जो कि इस पर एक उत्पाद है, जैसे घटक पुस्तकालय) एक गंध है। अपवाद असाधारण स्थिति को संभालने के लिए हैं, बग नहीं, और उपयोगकर्ता (यानी एपीआई उपभोक्ता) की कमी नहीं।

सबसे लंबा उत्तर:
अमान्य तर्कों के अपवादों को तब तक लाजिमी है, जब तक आप एक पुस्तकालय नहीं लिखते।
मैं दो (या अधिक) कारणों से अभिकथन का उपयोग करना पसंद करता हूं:

  • दावे की जांच करने की जरूरत नहीं है, जबकि जोर देते हैं, और ArgumentNullException के खिलाफ परीक्षण हास्यास्पद लगता है (इसे आज़माएं)।
  • अभिकल्पना इकाई के इच्छित उपयोग को बेहतर ढंग से संप्रेषित करता है, और एक वर्ग व्यवहार विनिर्देश की तुलना में निष्पादन योग्य दस्तावेज होने के करीब है।
  • आप दावे के उल्लंघन का व्यवहार बदल सकते हैं। उदाहरण के लिए डिबग संकलन में एक संदेश बॉक्स ठीक है, ताकि आपका क्यूए आपको तुरंत इसके साथ मार देगा (आप अपनी आईडीई को उस रेखा पर तोड़ना जहां यह होता है), जबकि यूनिट टेस्ट में आप परीक्षण विफलता के रूप में जोर विफलता का संकेत कर सकते हैं ।

यहाँ क्या है अशक्त अपवाद से निपटने की तरह लग रहा है (व्यंग्यात्मक, जाहिर है):

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

अपवाद का उपयोग तब किया जाता है जब स्थिति अपेक्षित होती है लेकिन असाधारण (चीजें होती हैं जो उपभोक्ता के नियंत्रण से बाहर होती हैं, जैसे कि IO विफलता)। तर्क * अपवाद एक बग का संकेत है और (मेरी राय) परीक्षणों के साथ संभाला जाएगा और डीबेट के साथ सहायता करेगा।

BTW: इस विशेष मामले में, आप इंट के बजाय मंथ टाइप का इस्तेमाल कर सकते थे। जब यह सुरक्षा (पहलू # नियम)! टाइप करने की बात आती है तो C # कम हो जाता है, लेकिन कभी-कभी आप उन सभी बग को रोक सकते हैं (या संकलन समय पर पकड़ सकते हैं)।

और हां, माइक्रो सॉफ्ट इसके बारे में गलत है।


6
IMHO, अपवादों को भी फेंक दिया जाना चाहिए जब बुलाया विधि यथोचित रूप से आगे नहीं बढ़ सकती है। इसमें वह मामला शामिल है जब कॉलर ने फर्जी तर्क पारित किए हैं। इसके बदले आप क्या करेंगे? वापसी -1?
जॉन सॉन्डर्स

1
यदि अमान्य तर्कों के कारण एक आंतरिक कार्य विफल हो जाता है, तो वैधता के लिए परीक्षण तर्कों के पक्ष और विपक्ष क्या हैं, या आंतरिक फ़ंक्शन से एक InvalidArgumentException को पकड़ना और इसे अधिक जानकारीपूर्ण के साथ लपेटना है? उत्तरार्द्ध दृष्टिकोण सामान्य मामले में प्रदर्शन में सुधार करने के लिए प्रतीत होता है, लेकिन मैंने इसे बहुत अधिक नहीं देखा है।
सुपरकैट

इस प्रश्न के आसपास एक त्वरित Google खोज इंगित करती है कि सामान्य अपवाद को फेंकना सभी का सबसे खराब अभ्यास है। तर्क की मुखरता के संबंध में, मैं इसमें छोटे व्यक्तिगत परियोजनाओं पर योग्यता देखता हूं, लेकिन उद्यम अनुप्रयोगों पर नहीं जहां आवेदन के खराब कॉन्फ़िगरेशन या खराब समझ के कारण अवैध तर्क सबसे अधिक संभावना है।
मैक्स

0

एक मानक तर्क है कि आप उपयोग कर सकते हैं, या आप उप-वर्ग बना सकते हैं और अपना खुद का बना सकते हैं। कई विशिष्ट तर्क अपवाद कक्षाएं हैं:

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

जो भी सबसे अच्छा काम करता है।


1
मैं लगभग सभी मामलों से असहमत हूं; बशर्ते .NET तर्क * अपवाद कक्षाएं बहुत अधिक उपयोग की जाती हैं और आपको समस्या के उपभोक्ता को सूचित करने के लिए पर्याप्त विशिष्ट जानकारी प्रदान करने की क्षमता प्रदान करती हैं।
STW

स्पष्ट करने के लिए - मैं तर्क * अपवाद वर्गों से प्राप्त होने के लगभग सभी मामलों से असहमत हूं। .NET तर्क निष्कासन अपवादों में से एक का उपयोग करना एक वर्णनात्मक और स्पष्ट संदेश, कमोबेश हर स्थिति के लिए पर्याप्त विवरण प्रदान करता है जहां तर्क अमान्य हैं।
STW

सहमत हुए, लेकिन मैं केवल उपलब्ध विकल्पों का वर्णन कर रहा था। मुझे निश्चित रूप से "पसंदीदा" विधि के बारे में अधिक स्पष्ट होना चाहिए था।
स्कॉट एम।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.