2009-09-28 10 views
39

मेरे आवेदन में मुझे एक अपवाद फेंकने की ज़रूरत है यदि किसी विशिष्ट वर्ग की संपत्ति शून्य या खाली है (यदि यह एक स्ट्रिंग है)। मुझे यकीन नहीं है कि इस मामले में उपयोग करने का सबसे अच्छा अपवाद क्या है। मैं एक नया अपवाद बनाने से नफरत करता हूं और मुझे यकीन नहीं है कि अगर इस मामले में ArgumentNullException उपयुक्त है।कोई अपवाद प्रकार का उपयोग करने के लिए जब कोई संपत्ति शून्य नहीं हो सकती है?

क्या मुझे एक नया अपवाद बनाना चाहिए या कोई अपवाद है जिसका मैं उपयोग कर सकता हूं?

मुझे एप्लिकेशन अपवाद को फेंकने की कोई बात नहीं है।

+0

ध्यान रखें कि गुण भी सिंटेक्टिक शर्करा विधियां हैं। – Dykam

+0

एक संबंधित रोचक चर्चा: http://stackoverflow.com/questions/1488472/best-practices-throwing-exceptions-from-properties – Joren

उत्तर

65

MSDN guidelines for standard exceptions कहता है:

संपत्ति setters के अंतर्निहित मूल्य पैरामीटर का नाम के लिए उपयोग मूल्य करो।

निम्न उदाहरण कोड एक संपत्ति है कि एक अपवाद है, तो फोन करने वाले एक अशक्त तर्क गुजरता फेंकता है पता चलता है।

public IPAddress Address 
{ 
    get 
    { 
     return address; 
    } 
    set 
    { 
     if(value == null) 
     { 
      throw new ArgumentNullException("value"); 
     } 
     address = value; 
    } 
} 

साथ ही, MSDN guidelines for property design कहते हैं:

बचें फेंकने संपत्ति ही टिककर खेल से अपवाद नहीं।

संपत्ति प्राप्तकर्ता बिना किसी पूर्व शर्त के संचालन सरल होना चाहिए। यदि कोई गेटटर अपवाद फेंक सकता है, संपत्ति को फिर से डिजाइन करने पर विचार करें एक विधि बनें। यह सिफारिश सूचकांक पर लागू नहीं होती है। इंडेक्स अमान्य तर्कों के कारण अपवाद फेंक सकते हैं।

यह संपत्ति सेटर से अपवाद फेंकने के लिए मान्य और स्वीकार्य है।

तो null पर सेटर में ArgumentNullException फेंक, और ArgumentException रिक्त स्ट्रिंग पर, और गेटर में कुछ भी नहीं है। चूंकि सेटर फेंकता है और केवल आपके पास बैकिंग फ़ील्ड तक पहुंच है, इसलिए यह सुनिश्चित करना आसान है कि इसमें अमान्य मान नहीं होगा। गेटर फेंकने के बाद व्यर्थ है। हालांकि यह Debug.Assert का उपयोग करने के लिए एक अच्छी जगह हो सकती है।

  1. बस लौट जो कुछ संपत्ति और दस्तावेज़ उपयोग अनुबंध के हिस्से के रूप में इस व्यवहार में है:

    तुम सच में एक उचित डिफ़ॉल्ट प्रदान नहीं कर सकते, तो मैं तुम्हें तीन विकल्प हैं लगता है। कॉलर को इसके साथ सौदा करने दें। आप कन्स्ट्रक्टर में वैध मान भी मांग सकते हैं। हालांकि यह आपके आवेदन के लिए पूरी तरह से अनुचित हो सकता है।

  2. गुणों के अनुसार संपत्ति को बदलें: एक अस्थायी मान पारित करने पर एक सेटर विधि, और InvalidOperationException फेंकने वाली गेटर विधि जब संपत्ति को वैध मान कभी नहीं दिया गया था।

  3. गेटटर से InvalidOperationException फेंक दें, क्योंकि आप विचार कर सकते हैं कि 'संपत्ति कभी असाइन नहीं की गई है'। जबकि आपको आमतौर पर गेटर्स से फेंकना नहीं चाहिए, मुझे लगता है कि यह अपवाद बनाने का एक अच्छा कारण हो सकता है।

आप विकल्प 2 या 3 चुनते हैं, तो आप भी एक TryGet- विधि है कि एक bool जो अगर संपत्ति एक वैध मान पर सेट कर दिया गया है इंगित करता है देता है को शामिल करना चाहिए, और इसलिए एक out पैरामीटर में है कि मान देता है, तो । अन्यथा आप InvalidOperationException को संभालने के लिए कॉलर्स को तैयार करने के लिए मजबूर करते हैं, जब तक कि वे पहले संपत्ति को स्वयं सेट नहीं कर लेते हैं और इस प्रकार जानते हैं कि यह फेंक नहीं देगा। int.Parse बनाम int.TryParse की तुलना करें।

मैं TryGet विधि के साथ विकल्प 2 का उपयोग करने का सुझाव दूंगा। यह किसी भी दिशानिर्देश का उल्लंघन नहीं करता है और कॉलिंग कोड पर न्यूनतम आवश्यकताओं को लागू करता है।


अन्य सुझावों
ApplicationException बारे में जिस तरह से बहुत सामान्य है। ArgumentExceptionnull के लिए थोड़ा सा सामान्य है, लेकिन अन्यथा ठीक है।MSDN docs again:

सर्वाधिक विशिष्ट (सबसे व्युत्पन्न) अपवाद है कि है उचित फेंक है। उदाहरण के लिए यदि एक विधि एक अशक्त तर्क (दृश्य बेसिक में कुछ भी) प्राप्त करता है, यह बजाय System.ArgumentNullException इसके आधार प्रकार System.ArgumentException की फेंक चाहिए।

वास्तव में आप सभी (docs) पर ApplicationException उपयोग नहीं करना चाहिए: टी से System.Exception वर्ग बल्कि:

टी से कस्टम अपवाद प्राप्त करें System.ApplicationException वर्ग।

यह मूल रूप से सोचा था कि कस्टम अपवाद ApplicationException वर्ग से निकाले जाते हैं चाहिए था, हालांकि, यह महत्वपूर्ण मूल्य जोड़ने के लिए नहीं मिला है। अधिक जानकारी के लिए, अपवादों को संभालने के लिए सर्वोत्तम अभ्यास देखें।

InvalidOperationException के लिए जब एक विधि या संपत्ति को तर्क अमान्य हैं नहीं करना है, लेकिन जब एक पूरे के रूप आपरेशन अमान्य है (docs) के लिए। यह सेटर से फेंका नहीं जाना चाहिए:

यदि कोई अनुचित स्थिति एक System.InvalidOperationException अपवाद फेंक मत करो। सिस्टम। इन्वालिडऑपरेशन अपवाद को फेंक दिया जाना चाहिए यदि ऑब्जेक्ट की वर्तमान स्थिति के बाद कोई प्रॉपर्टी सेट या विधि कॉल उपयुक्त नहीं है। उदाहरण के लिए, एक System.IO.FileStream को लिखने के लिए जो खोला गया है उसे एक सिस्टम फेंकना चाहिए। अविश्वसनीय अपवाद अपवाद अपवाद।

संयोग से, InvalidOperationException जब कार्रवाई अमान्य वस्तु की वर्तमान स्थिति के लिए है के लिए है। यदि ऑपरेशन पूरी कक्षा के लिए हमेशा अमान्य है, तो आपको NotSupportedException का उपयोग करना चाहिए।

+0

@ जोरेन, @ वादीम इंगित करता है कि उसे एक डिफ़ॉल्ट प्रशिक्षक की आवश्यकता है और इस क्षेत्र के लिए उचित डिफ़ॉल्ट नहीं है, इसलिए बसटर की निगरानी करना उसके परिदृश्य के लिए पर्याप्त नहीं होगा। – bdukes

+0

आप सही हैं, मैं अपना जवाब संपादित करूंगा। – Joren

+0

@ जोरेन, उत्कृष्ट प्रतिक्रिया। – Vadim

1

क्या निर्माता इसे गैर-शून्य मान पर सेट करता है? यदि ऐसा है तो मैं बसटर से ArgumentNullException फेंक दूंगा।

4

मैं InvalidOperationException फेंक दूंगा। एमएसडीएन का कहना है कि "जब ऑब्जेक्ट की वर्तमान स्थिति के लिए एक विधि कॉल अमान्य है तो इसे फेंक दिया जाता है।"

+1

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

+2

यदि ऑब्जेक्ट ऐसी स्थिति में था कि आप संपत्ति सेटटर का उपयोग करने के लिए अमान्य होगा तो आप 'InvalidOperationException' फेंक देंगे। यही है, * ऑपरेशन * स्वयं अमान्य है। एमएसडीएन दस्तावेज़ "सिस्टम को लिखने के लिए" System.IO.FileStream' का उदाहरण देते हैं जो पढ़ने के लिए खोला गया है "। – Joren

+0

मुझे लगता है कि हम क्या कह रहे हैं के सटीक परिदृश्य को नहीं जानते हैं। मैं इस धारणा के तहत काम कर रहा हूं कि हम एक वर्ग की विधि बुला रहे हैं, और विधि के भीतर उस वर्ग की संपत्ति का उपयोग करने की कोशिश कर रहे हैं। उस स्थिति में, ऑब्जेक्ट उस विधि के लिए अमान्य है जिसे कॉल किया जा रहा है (क्योंकि विधि को विधि से पहले सेट करने की आवश्यकता है)। ऐसा लगता है कि @ जेरेडपार उस परिदृश्य पर विचार कर रहा है जहां तर्क पर एक संपत्ति प्रारंभ नहीं की गई है। उस स्थिति में, 'ArgumentException' का उनका सुझाव सबसे अधिक समझ में आता है। – bdukes

2

अच्छा, यह एक तर्क नहीं है, यदि आप किसी वर्ग की संपत्ति का संदर्भ दे रहे हैं। इसलिए, आपको ArgumentException या ArgumentNullException का उपयोग नहीं करना चाहिए।

NullReferenceException होगा अगर आप केवल चीजें अकेले छोड़ दें, तो मुझे लगता है कि आप जो खोज रहे हैं वह नहीं है।

तो, एप्लिकेशनएक्सप्शन या अमान्यऑपरेशन अपवाद का उपयोग करना शायद आपकी सबसे अच्छी शर्त होगी, जिससे त्रुटि का वर्णन करने के लिए एक सार्थक स्ट्रिंग देना सुनिश्चित हो।

+1

मुझे यकीन है कि .NET Framework में कक्षाएं हैं जो किसी संपत्ति के सेटटर से ArgumentException फेंकती हैं। मुझे याद नहीं है कि बिल्कुल कहां है लेकिन मुझे याद आ रहा है। आप तर्क दे सकते हैं कि यह "उचित" नहीं हो सकता है, भले ही ढांचे ने उदाहरण निर्धारित किया हो। – Tinister

2

अगर कोई शून्य निर्दिष्ट करने का प्रयास करता है तो यह ArgumentNullException को फेंकना उचित है।

एक संपत्ति को कभी भी एक पढ़ाई ऑपरेशन पर फेंकना नहीं चाहिए।

+0

आपको यह विचार कहां मिलता है कि किसी संपत्ति को कभी भी पढ़ने के ऑपरेशन पर फेंकना नहीं चाहिए? यह निश्चित रूप से पर्याप्त आसानी से हो सकता है। –

+1

@ जॉन मुझे नहीं लगता कि उनका मुद्दा यह था कि यह केवल इतना नहीं है कि इसे नहीं करना चाहिए। –

+1

@ जॉन फिशर: क्वेलिना, क्रिस्टस्टोफ और ब्रैड अब्राम: "फ्रेमवर्क डिजाइन दिशानिर्देश। सम्मेलन, मुहावरे, और पैटर्न पुन: प्रयोज्य .NET पुस्तकालयों", एडिसन-वेस्ले, 2006. पी। 121 - अन्य स्रोतों के बीच। –

1

यदि समस्या यह है कि तर्क का सदस्य है, और तर्क स्वयं नहीं है, तो मुझे लगता है कि सबसे अच्छा विकल्प अधिक सामान्य ArgumentException है। ArgumentNullException यहां काम नहीं करता है क्योंकि तर्क वास्तव में शून्य नहीं है। इसके बजाय आपको अधिक सामान्य "कुछ तर्क गलत है" अपवाद प्रकार की आवश्यकता है।

निर्माता के लिए एक विस्तृत संदेश यहाँ

+0

आपका मतलब क्या है "कन्स्ट्रक्टर के लिए एक विस्तृत संदेश"? मेरे पास एक डिफ़ॉल्ट कन्स्ट्रक्टर होना चाहिए। – Vadim

+0

@ वादीम एक विस्तृत कारण बताता है कि तर्क अपवाद क्यों फेंक दिया जा रहा है। उदाहरण के लिए "पैरामीटर फू का प्रॉपर्टी ब्लाह गैर-शून्य" – JaredPar

+0

@ वाडिम होना चाहिए, वह अपवाद के कंडक्टर का जिक्र कर रहा है, न कि आपके ऑब्जेक्ट के कन्स्ट्रक्टर। – bdukes

1

यह शून्य या खाली नहीं किया जा सकता है, तो बहुत उपयुक्त होगा, अपने सेटर शून्य या खाली मूल्यों की अनुमति देते हैं, या एक ArgumentException फेंक यदि यह मामला है नहीं किया है।

इसके अलावा, संपत्ति को कन्स्ट्रक्टर में सेट करने की आवश्यकता है।

इस तरह आप बाद में वापस आने के बजाय वैध मान लागू करते हैं और कह रहे हैं कि खाता खाता शेष निर्धारित नहीं हो सकता है क्योंकि खाता सेट नहीं है।

लेकिन, मैं bduke की प्रतिक्रिया से सहमत हूं।

+1

मेरे पास डिफ़ॉल्ट कन्स्ट्रक्टर होना चाहिए। – Vadim

+0

आप कुछ वैध डिफ़ॉल्ट मान नहीं डाल सकते हैं जिसे मैं इसे निर्माता में लेता हूं? –

+1

दुर्भाग्य से मैं अनुमान लगाने वाला गेम नहीं खेल सकता। मुझे नहीं पता कि रन-टाइम पर मूल्य क्या निर्धारित किया जाना चाहिए। – Vadim

1

ArgumentNullException की व्याख्या को खींचने के लिए एक उदाहरण है जिसका अर्थ है "स्ट्रिंग तर्क शून्य या खाली है": System.Windows.Clipboard.SetText इस मामले में एक ArgumentNullException फेंक देगा।

तो मैं कुछ भी नहीं अपनी संपत्ति सेटर में अधिक सामान्य ArgumentException के बजाय इस का उपयोग कर के साथ कुछ गलत है, बशर्ते आप इसे दस्तावेज़ देखना होगा।

0

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

संबंधित मुद्दे

 संबंधित मुद्दे