2011-03-28 20 views
8

के बीच चयन करना मैंने एक कक्षा बनाई है जो फ़ाइल से कुछ दस्तावेज़ों को पार करती है।अपवाद और वापसी मूल्य

class Parser 
{ 
    public Parse(string fileName) 
    { 
    /// 
    } 
} 

कभी-कभी उस मामले पार्सर में त्रुटियों को पार्स है कुछ डेटा वापस जाने के लिए हो सकता है। मैंने इसके लिए विशेष कक्षा बनाई है।

class ParsingError 
{ 
// some data 
} 

मैं इस तरह की त्रुटियों से सही ढंग से कैसे निपट सकता हूं। मेरे पास कम से कम दो विकल्प हैं:

मेरा अपना अपवाद या वापसी मूल्य बनाएं।

विकल्प एक

myParser.Parse(fileName, out error); 

विकल्प दो

try 
{ 
    myParser.Parse(fileName) 
} 

catch(MyParsingException ex) 
{ 
    // use ex.Error field 
} 

अद्यतन

मैं विचारधारा गलत नहीं कर रहा हूँ, तो पीछे अपवाद है कि यह कुछ असाधारण के साथ सौदा करना चाहिए, यह कुछ परिस्थिति है कि विधि का निपटारा करने का इरादा नहीं है।

इस ओर जाता है मुझे आश्चर्य है अगर उदाहरण के लिए:

पार्सर फ़ाइल में अज्ञात क्षेत्र पाता है, या एन्कोडिंग

कि एक असाधारण मामले पर विचार किया जाएगा गलत क्या है?

+0

स्वाद का मामला? पार्सफंक्शन जो मैं सी # में जानता हूं अपवाद का उपयोग करता हूं। – jwillmer

+0

संभावित डुप्लिकेट [।एनईटी रिटर्न वैल्यू बनाम अपवाद डिजाइन प्रश्न फेंक दिया गया है] (http://stackoverflow.com/q/4884539/102112) – Alex

+0

क्या इस प्रश्न के अलावा कुछ और बेहतर है? उस प्रश्न का उत्तर कई प्रश्नों में दिया गया है उदा। http://stackoverflow.com/questions/99683/which-and-why-do-you-prefer-exceptions-or-return-codes – StuperUser

उत्तर

14

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

+0

अच्छा जवाब। हालांकि, मेरे पास अभी भी एक सवाल है। यह तय नहीं कर रहा है कि यह आपके व्यक्तिगत फैसले पर निर्भर कैसे है? ऐसा लगता है। उदाहरण के लिए, जब आप "asd" स्ट्रिंग को एक पूर्णांक में कनवर्ट करने का प्रयास करते हैं, तो एक अपवाद फेंक दिया जाएगा। क्या हम कह सकते हैं कि यह सामान्य नहीं है, भले ही यह त्रुटि एक सामान्य आम है? –

+0

@अनार: ऐसे मामलों में आपके पास आम तौर पर दो अलग-अलग फ़ंक्शन होते हैं (या ध्वज के साथ एक) - एक "पार्स का प्रयास करें और एक त्रुटि कोड लौटाएगा" और दूसरा "इसे पार्स करेगा और कुछ भी अपवाद फेंक देगा" और दूसरा एक आम तौर पर आंतरिक रूप से पहले व्यक्ति को कॉल करेगा और डेवलपर तब तय करेगा कि किस का उपयोग करना है। वह उपयोगकर्ता इनपुट से निपटने के लिए पहले और दूसरे और एक विश्वसनीय स्रोत से आने वाली किसी चीज़ को पार्स करने के लिए उपयोग करेंगे। – sharptooth

+0

इस संदर्भ में, मुझे समझने में क्या कठिनाई है कि एक "_a विश्वसनीय स्रोत_" को कैसे परिभाषित कर सकता है ताकि पारसी (TryParse नहीं) का उपयोग किया जा सके? मैं यह कहने की कोशिश कर रहा हूं कि यह भरोसेमंद/भरोसेमंद चीज व्याख्या का विषय है और हमारी व्याख्या स्वाभाविक रूप से गलत हो सकती है। हमारे अपवाद-झूठी व्याख्याओं पर निर्भर अपवादों या वापसी मूल्यों का उपयोग क्यों कर रहे हैं? –

1

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

3

मैं विकल्प तीन

ParseResult result = myParser.Parse(filename) 

यहाँ ParseResult पार्स के परिणाम, सकारात्मक और नकारात्मक दोनों के बारे में और अधिक विस्तार प्रदान कर सकते हैं के साथ जाना होगा।

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

0

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

मान लें कि मैं एक XML सत्यापनकर्ता लिख ​​रहा हूं, फिर एक त्रुटि लौटने का तरीका है। अगर मैं एक एक्सएमएल कॉन्फ़िगरेशन पार्सर लिख रहा हूं, तो एक अपवाद अधिक उपयुक्त लगेगा।

2

यह निर्भर करता है कि MyParsingException सिस्टम से एक व्युत्पन्न वर्ग है। निष्पादन, या इसमें फ़ाइल को पार्स करने का प्रयास करते समय गलत क्या है, इसके बारे में अतिरिक्त जानकारी है। अगर ऐसी कोई जानकारी है, तो मुझे लगता है कि पार्स विधि शायद एक स्ट्रिंग लौटाने चाहिए, या अशक्त यदि कोई त्रुटि उत्पन्न हुई:

public string Parse(string fileName) 
{ 
    string res = null; 
    try 
    { 
     /// parse the file, assign parse result to res 
    } 
    catch 
    { 
     res = null; 
    } 
    return res; 
} 

या, यदि अपवाद वास्तव में उपयोगी है, फ़ाइल के बारे में जानकारी (नाम में शामिल है), लाइन नंबर ... आदि:

public string Parse(string fileName) 
{ 
    string res = null; 
    int errorLine = -1; 
    try 
    { 
     // foreach line of text to parse -- errorLine = lineNumber; 
     /// parse the file, assign parse result to res 
    } 
    catch (Exeption ex) 
    { 
     MyParsingException myEx= new MyParsingException ("parsing error", ex); 
     myEx.Data["fileName"] = fileName; 
     myEx.data["lineNumber"] = errorLine ; 
     throw myEx; 
    } 
    return res; 
} 
// then you can have some really useful info: 

try 
{ 
    myParser.Parse(fileName) 
} 
catch(MyParsingException ex) 
{ 
    // use ex.Data to get the "fileName" and "lineNumber" properties. 
} 
5

अपवादों पर .NET भूमि का दर्शन अन्य प्लेटफार्मों की तुलना में थोड़ा अलग है। .NET भूमि में यह लंबे समय तक नहीं लगता है कि आप ओझेड में नहीं हैं, और यह अपवाद अक्सर फेंक दिया जाता है।

एमएसडीएन से .NET 4: त्रुटि कोड वापस न करें। अपवाद फ्रेमवर्क में त्रुटियों की रिपोर्ट करने का प्राथमिक माध्यम हैं।

एमएसडीएन से .NET 4.5: एक अपवाद किसी भी त्रुटि स्थिति या अप्रत्याशित व्यवहार है जो किसी निष्पादन कार्यक्रम द्वारा सामना किया जाता है।

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

+0

.NET 4.5 पर एमएसडीएन से बयान का दूसरा भाग जोड़ा जाना चाहिए: "आपके कोड में या आपके द्वारा कॉल किए गए कोड (जैसे साझा लाइब्रेरी) में गलती के कारण अपवाद उठाए जा सकते हैं ...", जिसका अर्थ है ** डेटा दोषों के लिए नहीं, कोड दोषों के लिए अपवाद हैं **। – Lightman

2

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

अक्सर एक विधि के लेखक यह नहीं जान सकते कि कौन सा परिदृश्य अपने कॉलर्स पर लागू होगा (वास्तव में, कुछ कॉलर्स के लिए यह एक पैटर्न और कुछ अन्य फिट करने के लिए आम है)।

Thing GetThing(int param1, string param2); 
bool TryGetThing(int param1, string param2, out Thing result); 

निश्चित रूप से कॉल सीमित, एक पैटर्न या अन्य फिट करने के लिए हालांकि मैं विशेष रूप से कार्यान्वयन पसंद नहीं है की तुलना में बेहतर अवधारणा है कि: इस से निपटने के माइक्रोसॉफ्ट के पसंदीदा तरीका पैटर्न का उपयोग करने के लिए है। माइक्रोसॉफ्ट स्पष्ट रूप से पैरामीटर के साथ एक विधि का उपयोग करने के बजाय अलग-अलग तरीकों का उपयोग करने की सिफारिश करता है जो इंगित करता है कि विफलता को अपवाद फेंकना चाहिए, लेकिन यह दर्शन लागत पर आता है: इसका मतलब है कि GetThing या TryGetThing के चरणों में से एक के साथ किया जा सकता है "do" या "try" विधि, GetThing और TryGetThing के लिए कोड को बड़े पैमाने पर डुप्लिकेट करना होगा, एक कॉलिंग "डू" विधियों और अन्य कॉलिंग "कोशिश करें" विधियों के साथ।

एक वैकल्पिक दृष्टिकोण एक प्रतिनिधि या इंटरफेस-प्रकार ऑब्जेक्ट होना चाहिए जो इंगित करता है कि अपवाद होने पर "कोशिश" विधि क्या करनी चाहिए।

Thing TryGetThing(int param1, string param2, bool ThrowOnError, out ErrorInfo errInf); 
संभवतः एक अधिभार जो, अगर पिछले दो मापदंडों छोड़े गए हैं, ThrowOnError के लिए true साथ ऊपर कॉल होगा, और errInf के लिए एक डमी चर के साथ

: उदाहरण के लिए, एक एक समारोह हो सकता था। यदि TryGetThing द्वारा उपयोग की जाने वाली विधियां समान पैटर्न का पालन करती हैं, तो यह कोशिश/करने के मामलों के लिए कोड डुप्लिकेट किए बिना उन्हें कॉल करने में सक्षम हो सकती है।

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