अमान्य जेनेरिक प्रकार तर्क के लिए सर्वश्रेष्ठ अपवाद


106

मैं वर्तमान में UnconstrainedMelody के लिए कुछ कोड लिख रहा हूं जिसमें enums के साथ सामान्य तरीके हैं।

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

बस इस ठोस बनाने के लिए, अगर मेरे पास कुछ ऐसा है:

// Returns a value with all bits set by any values
public static T GetBitMask<T>() where T : struct, IEnumConstraint
{
    if (!IsFlags<T>()) // This method doesn't throw
    {
        throw new ???
    }
    // Normal work here
}

फेंकने के लिए सबसे अच्छा अपवाद क्या है? ArgumentExceptionतार्किक लगता है, लेकिन यह एक सामान्य तर्क के बजाय एक प्रकार का तर्क है, जो आसानी से चीजों को भ्रमित कर सकता है। क्या मुझे अपनी TypeArgumentExceptionकक्षा शुरू करनी चाहिए ? का उपयोग करें InvalidOperationException? NotSupportedException? और कुछ?

मैं चाहता हूँ बल्कि नहीं जब तक कि यह स्पष्ट रूप से करने के लिए सही बात है इस के लिए अपने ही अपवाद पैदा करते हैं।


मैं आज एक सामान्य विधि लिखने में इस पर लड़खड़ा गया, जहाँ उपयोग किए जा रहे प्रकारों पर अतिरिक्त आवश्यकताओं को रखा गया है, जिन्हें अड़चनों के साथ नहीं बताया जा सकता है। मुझे आश्चर्य था कि बीसीएल में पहले से ही एक अपवाद प्रकार नहीं मिला। लेकिन यह सटीक दुविधा वह थी जिसका मैंने कुछ दिन पहले उसी परियोजना में एक सामान्य के लिए सामना किया था जो केवल एक झंडे की विशेषता के साथ काम करेगी। डरावना!
ज़ोल्टन

जवाबों:


46

NotSupportedException ऐसा लगता है कि यह स्पष्ट रूप से फिट बैठता है, लेकिन प्रलेखन स्पष्ट रूप से बताता है कि इसका उपयोग एक अलग उद्देश्य के लिए किया जाना चाहिए। MSDN वर्ग टिप्पणियों से:

ऐसी विधियां हैं जो आधार वर्ग में समर्थित नहीं हैं, इस अपेक्षा के साथ कि ये विधियां इसके बजाय व्युत्पन्न वर्गों में लागू की जाएंगी। व्युत्पन्न वर्ग बेस क्लास से विधियों के केवल सबसेट को लागू कर सकता है, और असमर्थित विधियों के लिए NotSupportedException को फेंक सकता है।

बेशक, वहाँ एक रास्ता है जिसमें NotSupportedExceptionस्पष्ट रूप से काफी अच्छा है, विशेष रूप से इसका सामान्य ज्ञान अर्थ दिया जाता है। यह कहने के बाद, मुझे यकीन नहीं है कि यह सही है।

अप्रशिक्षित मेलोडी के उद्देश्य को देखते हुए ...

विभिन्न उपयोगी चीजें हैं जो जेनेरिक विधियों / कक्षाओं के साथ की जा सकती हैं, जहां "T: enum" या "T: प्रतिनिधि" का एक प्रकार का अवरोध है - लेकिन दुर्भाग्य से, वे C # में निषिद्ध हैं।

यह उपयोगिता पुस्तकालय ildasm / ilasm का उपयोग कर निषेध के आसपास काम करता है ...

... ऐसा लगता है कि Exceptionसबूत के उच्च बोझ के बावजूद एक नया क्रम हो सकता है, जिसे हमें कस्टम बनाने से पहले पूरा करना होगा ExceptionsInvalidTypeParameterExceptionपुस्तकालय में कुछ उपयोगी हो सकता है (या शायद नहीं - यह निश्चित रूप से एक किनारे का मामला है, ठीक है?)।

क्या ग्राहकों को बीसीएल अपवादों से अलग करने में सक्षम होना चाहिए? जब एक ग्राहक गलती से एक वेनिला का उपयोग करके यह कह सकता है enum? कस्टम अपवाद कक्षा लिखते समय किन कारकों को ध्यान में रखा जाना चाहिए, इस सवाल के स्वीकृत जवाब से आप कैसे जवाब देंगे ?


वास्तव में यह पहली बार में केवल आंतरिक-अपवाद को फेंकने के लिए लगभग लुभावना है, उसी तरह से जो कोड कॉन्ट्रैक्ट करता है ... मेरा मानना ​​है कि किसी को भी इसे पकड़ना नहीं चाहिए
जॉन स्कीट

बहुत बुरा यह सिर्फ अशक्त वापस नहीं कर सकता!
जेफ सनातन

25
मैं TypeArgumentException के साथ जा रहा हूं।
जॉन स्कीट

फ्रेमवर्क में अपवाद जोड़ने पर "प्रमाण का बोझ" अधिक हो सकता है, लेकिन कस्टम अपवादों को परिभाषित नहीं करना चाहिए। जैसे InvalidOperationExceptionकि icky चीजें हैं, क्योंकि "फू संग्रह बार को कुछ ऐसा जोड़ने के लिए कहता है जो पहले से मौजूद है, इसलिए बार IOE फेंकता है" और "फू संग्रह बार को कुछ जोड़ने के लिए कहता है, इसलिए बार Boz को कॉल करता है जो IOE को फेंकता है, जबकि बार इसकी उम्मीद नहीं करता है" क्या दोनों एक ही अपवाद प्रकार को फेंक देंगे; कोड जो पहले पकड़ने की उम्मीद कर रहा है वह बाद की उम्मीद नहीं करेगा। कहा जा रहा है ...
सुपरकैट

... मुझे लगता है कि एक फ्रेमवर्क अपवाद के पक्ष में तर्क कस्टम अपवाद की तुलना में अधिक सम्मोहक है। एनएसई की सामान्य प्रकृति यह है कि जब किसी वस्तु का संदर्भ सामान्य प्रकार के रूप में होता है, और कुछ नहीं बल्कि विशिष्ट प्रकार की सभी वस्तुएं जिनमें संदर्भ बिंदु एक क्षमता का समर्थन करेंगे, एक विशिष्ट प्रकार की क्षमता का उपयोग करने का प्रयास करते हैं, जो doesn 't समर्थन यह NSE फेंक देना चाहिए। मैं Foo<T>एक "सामान्य प्रकार" होने के लिए विचार करूंगा , और Foo<Bar>उस संदर्भ में "विशिष्ट प्रकार" होने के बावजूद, उनके बीच कोई "विरासत" संबंध नहीं है।
सुपरकैट

24

मैं NotSupportedException से बचना होगा। इस अपवाद का उपयोग उस फ्रेमवर्क में किया जाता है जहां कोई विधि लागू नहीं होती है और एक संपत्ति होती है जो यह संकेत देती है कि इस प्रकार के ऑपरेशन का समर्थन नहीं किया गया है। यह यहाँ फिट नहीं है

मुझे लगता है कि InvalidOperationException सबसे उपयुक्त अपवाद है जिसे आप यहां फेंक सकते हैं।


एनएसई के बारे में शीर्षकों के लिए धन्यवाद। अपने सहयोगियों से भी इनपुट का स्वागत करेंगे, btw ...
जॉन स्केट

मुद्दा यह है कि, बीसीएल में जॉन की जरूरत की कार्यक्षमता में कुछ भी समान नहीं है। संकलक इसे पकड़ने के लिए माना जाता है। यदि आप NotSupportedException से "प्रॉपर्टी" की आवश्यकता को हटा देते हैं, तो आपके द्वारा बताई गई चीजें (जैसे ReadOnly संग्रह) जॉन के मुद्दे के सबसे करीब हैं।
मेहरदाद अफश्री

एक बिंदु - मेरे पास एक IsFlags विधि है (यह सामान्य होने की एक विधि होनी चाहिए) जो यह संकेत देने की तरह है कि इस प्रकार का ऑपरेशन समर्थित नहीं है ... इसलिए उस अर्थ में एनएसई उपयुक्त होगा। यानी कॉल करने वाला पहले चेक कर सकता है
जॉन स्कीट

@Jon: मुझे लगता है, भले ही आप इस तरह के एक संपत्ति की जरूरत नहीं है , लेकिन अपने प्रकार के सभी सदस्यों को स्वाभाविक तथ्य यह है कि पर भरोसा Tहै एक enumके साथ सजाया Flagsहै, यह एनएसई फेंकने के लिए मान्य होगा।
मेहरदाद अफश्री

1
@Jon: StupidClrException;) एक मजेदार नाम बनाता है
Mehrdad Afshari

13

जेनेरिक प्रोग्रामिंग को अमान्य प्रकार के मापदंडों के लिए रनटाइम पर नहीं फेंकना चाहिए। यह संकलित नहीं होना चाहिए, आपके पास एक संकलन समय प्रवर्तन होना चाहिए। मुझे नहीं पता कि क्या IsFlag<T>()शामिल है, लेकिन शायद आप इसे एक संकलन समय प्रवर्तन में बदल सकते हैं, जैसे कि एक प्रकार बनाने की कोशिश करना जो केवल 'झंडे' के साथ बनाना संभव है। शायद कोई traitsवर्ग मदद कर सकता है।

अपडेट करें

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

यदि विफलता में स्वयं तर्क शामिल नहीं हैं, तो InvalidOperationException का उपयोग किया जाना चाहिए।

वहाँ विश्वास की कम से कम एक छलांग है, कि विधि मापदंडों की सिफारिशें भी जेनेरिक मापदंडों पर लागू की जानी हैं , लेकिन SystemException hierachy imho में कुछ भी बेहतर नहीं है।


1
नहीं, ऐसा कोई तरीका नहीं है कि यह संकलन समय पर विवश हो सकता है। IsFlag<T>यह निर्धारित करता है कि क्या एनम ने [FlagsAttribute]इसे लागू किया है, और सीएलआर में विशेषताओं के आधार पर बाधाएं नहीं हैं। यह एक आदर्श दुनिया में होगा - या इसे रोकने के लिए कोई और तरीका होगा - लेकिन इस मामले में यह काम नहीं करता है :(
जॉन स्केट

(हालांकि सामान्य सिद्धांत के लिए +1 - मैं इसे विवश करने में सक्षम होना पसंद करूंगा ।)
जॉन स्कीट

9

मैं NotSupportedException का उपयोग करता हूँ जैसा कि आप कह रहे हैं। विशिष्ट लोगों की तुलना में अन्य enums समर्थित नहीं हैं । यह निश्चित रूप से अपवाद संदेश में अधिक स्पष्ट रूप से कहा जाएगा।


2
NotSupportedException का उपयोग BCL में एक बहुत भिन्न उद्देश्य के लिए किया जाता है। यह यहाँ फिट नहीं है। blogs.msdn.com/jaredpar/archive/2008/12/12/...
JaredPar

8

मैं साथ चलूँगा NotSupportedException। जब ArgumentExceptionयह ठीक लगता है, तो यह वास्तव में अपेक्षित होता है जब किसी विधि को दिया गया तर्क अस्वीकार्य हो। एक प्रकार का तर्क वह वास्तविक विधि है जिसे आप कॉल करना चाहते हैं, एक वास्तविक "तर्क" नहीं है। InvalidOperationExceptionफेंक दिया जाना चाहिए जब आप जो ऑपरेशन कर रहे हैं वह कुछ मामलों में मान्य हो सकता है लेकिन विशेष स्थिति के लिए, यह अस्वीकार्य है।

NotSupportedExceptionस्वाभाविक रूप से असमर्थित होने पर फेंक दिया जाता है। उदाहरण के लिए, एक इंटरफ़ेस लागू करते समय जहां एक विशेष सदस्य एक वर्ग के लिए समझ में नहीं आता है। यह एक समान स्थिति की तरह दिखता है।


Mmm। यह अभी भी काफी सही नहीं लगता है, लेकिन मुझे लगता है कि यह इसके लिए सबसे करीबी चीज है।
जॉन स्कीट

जॉन: यह सही नहीं लगता क्योंकि हम स्वाभाविक रूप से उम्मीद करते हैं कि इसे कंपाइलर द्वारा पकड़ा जाए।
मेहरदाद अफशरी

हाँ। यह एक अजीब तरह की बाधा है जिसे मैं लागू करना चाहता हूं लेकिन नहीं कर सकता :)
जॉन स्कीट

6

जाहिर है, माइक्रोसॉफ्ट का उपयोग करता है ArgumentExceptionकि के लिए, के रूप में के उदाहरण पर प्रदर्शन किया Expression.Lambda <> , Enum.TryParse <> या Marshal.GetDelegateForFunctionPointer <> अपवाद अनुभाग में। मैं किसी भी उदाहरण को इंगित नहीं कर पाया, या तो (स्थानीय संदर्भ स्रोत खोजने के बावजूद ) TDelegateऔर TEnum

इसलिए, मुझे लगता है कि यह मानना ​​सुरक्षित है कि कम से कम Microsoft कोड में यह ArgumentExceptionसामान्य चर प्रकार के तर्क के लिए मूल चर से अलग उपयोग करने के लिए एक आम बात है। यह देखते हुए कि डॉक्स में अपवाद विवरण उन लोगों के बीच भेदभाव नहीं करता है, यह बहुत अधिक खिंचाव नहीं है, या तो।

उम्मीद है कि यह एक बार और सभी के लिए सवाल बातें तय करता है।


ढांचे में एक एकल उदाहरण नहीं, कोई मेरे लिए काफी है - स्थानों की संख्या मैं कहाँ लगता है एमएस अन्य मामलों में गरीब चुनाव किया है :) मैं प्राप्त नहीं कही जा TypeArgumentExceptionसे ArgumentException, बस क्योंकि एक प्रकार तर्क एक नियमित रूप से नहीं है बहस।
जॉन स्कीट

1
यह निश्चित रूप से "यह वही है जो एमएस लगातार करता है" के संदर्भ में अधिक सम्मोहक है। यह दस्तावेज़ीकरण के मिलान के संदर्भ में इसे और अधिक आकर्षक नहीं बनाता है ... और मुझे पता है कि सी # टीम में बहुत सारे लोग हैं जो नियमित तर्क और प्रकार के तर्कों के बीच अंतर के बारे में गहराई से परवाह करते हैं :) लेकिन उदाहरण के लिए धन्यवाद - वे बहुत मददगार हैं।
जॉन स्कीट

@ जोंन स्कीट: एक संपादन; अब इसमें अलग-अलग MS पुस्तकालयों से 3 उदाहरण शामिल हैं, सभी ArgumentException के साथ एक फेंक दिए गए दस्तावेज़ के रूप में; इसलिए यदि यह एक खराब विकल्प है, तो कम से कम यह एक लगातार खराब विकल्प है। ;) मुझे लगता है कि Microsoft मानता है कि नियमित तर्क और प्रकार तर्क दोनों तर्क हैं; और व्यक्तिगत रूप से, मुझे लगता है कि इस तरह की धारणा काफी उचित है। ^ ^ '
ऐलिस

आह, कभी नहीं, लगता है कि आप पहले से ही देखा है। मैं खुशी से मदद कर सकता है। ^ ^
ऐलिस

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


2

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


इसके अलावा डेवलपर को XML टिप्पणियों में फेंके गए सभी अपवादों का दस्तावेजीकरण करना चाहिए।
एरिक श्नाइडर

1

कैसे NotSupportedException से विरासत में मिला। जबकि मैं @ मेहरदाद से सहमत हूं कि यह सबसे अधिक समझ में आता है, मैं आपकी बात सुनता हूं कि यह पूरी तरह से फिट नहीं लगता है। तो NotSupportedException से विरासत में मिला, और इस तरह से आपके API के खिलाफ कोडिंग करने वाले लोग अभी भी NotSupportedException को पकड़ सकते हैं।


1

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

इस मामले में, मैं झंडे की जांच में विफलता के लिए एक आर्ग्यूमेंट अपवाद को फेंक दूंगा। यह वास्तव में वरीयता के लिए नीचे है। कुछ कोडिंग मानकों को मैंने देखा है कि यह परिभाषित करने के लिए कि इस प्रकार के परिदृश्यों में किस प्रकार के अपवादों को फेंक दिया जाना चाहिए।

यदि उपयोगकर्ता किसी ऐसी चीज से गुजरने की कोशिश कर रहा है जो कि एनम नहीं थी तो मैं एक InvalidOperationException को फेंक दूंगा।

संपादित करें:

अन्य लोग एक दिलचस्प बात उठाते हैं कि यह समर्थित नहीं है। एक NotSupportedException के साथ मेरी एकमात्र चिंता यह है कि आम तौर पर वे अपवाद होते हैं जो "डार्क मैटर" को सिस्टम में लाए जाने पर, या इसे किसी अन्य तरीके से डालने के लिए फेंक दिए जाते हैं, "इस पद्धति को इस इंटरफ़ेस पर सिस्टम में जाना चाहिए, लेकिन हम जीत गए 2.4 संस्करण तक इसे चालू न करें

मैंने यह भी देखा है कि NotSupportedException को लाइसेंसिंग अपवाद के रूप में फेंक दिया गया है "आप इस सॉफ़्टवेयर के मुफ्त संस्करण को चला रहे हैं, यह फ़ंक्शन समर्थित नहीं है"।

2 संपादित करें:

एक और संभव एक:

System.ComponentModel.InvalidEnumArgumentException  

इनकाउंटर करने वाले अमान्य तर्कों का उपयोग करते समय अपवाद को फेंक दिया जाता है।


मैंने इसे एक एनम होने के लिए विवश किया है (कुछ गुड़ की पॉकरी के बाद) - यह केवल झंडे हैं जिनके बारे में मैं चिंतित हूं।
जॉन स्कीट

मुझे लगता है कि उन लाइसेंसधारी लोगों को LicensingExceptionविरासत में मिली एक श्रेणी का उदाहरण फेंकना चाहिए InvalidOperationException
मेहरदाद अफश्री

मैं सहमत हूं कि मेहरदाद, अपवाद दुर्भाग्य से उन क्षेत्रों में से एक है जहां ढांचे में बहुत ग्रे है। लेकिन मुझे यकीन है कि यह बहुत सारी भाषाओं के लिए समान है। (नहीं कह रहा था कि मैं vb6 की रनटाइम त्रुटि 13 हीहे पर वापस जाऊंगा)
पीटर

1

मैं भी InvalidOperationException को वोट करूंगा। मैंने .NET अपवाद पर एक (अपूर्ण) फ्लोचार्ट किया था जो फ्रेमवर्क डिज़ाइन दिशानिर्देश 2 एड पर आधारित दिशानिर्देश फेंक रहा था अगर किसी की दिलचस्पी है तो थोड़ी देर रुकें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.