अपवाद, त्रुटि कोड और भेदभाव रहित संघ


80

मैंने हाल ही में एक सी # प्रोग्रामिंग नौकरी शुरू की है, लेकिन मुझे हास्केल में काफी पृष्ठभूमि मिली है।

लेकिन मैं समझता हूं कि C # एक ऑब्जेक्ट-ओरिएंटेड भाषा है, मैं एक गोल खूंटी को एक वर्ग छेद में मजबूर नहीं करना चाहता।

मैंने Microsoft से जो लेख प्रस्तुत किया है, उसमें मैंने लिखा है:

त्रुटि कोड वापस न करें

लेकिन हास्केल के लिए उपयोग किया जा रहा है, मैं सी # डेटा प्रकार का उपयोग कर रहा हूं OneOf, परिणाम को "बाएं" मान के रूप में "सही" मान या त्रुटि (अक्सर एक एन्यूमरेशन) के रूप में लौटा रहा हूं ।

यह बहुत हद तक Eitherहास्केल के सम्मेलन की तरह है ।

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

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

लेकिन यह ऐसा तरीका नहीं है जो Microsoft सुझाता है।

उपयोग कर रहा है OneOf"साधारण" अपवाद को संभालने के लिए अपवाद के बजाय (फ़ाइल की तरह नहीं मिला आदि) एक उचित दृष्टिकोण या यह भयानक बात है?


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

नोट मैं OneOf"मेमोरी से बाहर" जैसी चीजों के लिए उपयोग नहीं कर रहा हूं , जिन स्थितियों से मैं ठीक होने की उम्मीद नहीं करता हूं, वे अभी भी अपवादों को फेंक देंगे। लेकिन मैं काफी उचित मुद्दों की तरह महसूस करता हूं, जैसे कि उपयोगकर्ता इनपुट जो पार्स नहीं करता है, अनिवार्य रूप से "नियंत्रण प्रवाह" है और शायद अपवाद नहीं फेंकना चाहिए।


इसके बाद के विचार:

इस चर्चा से जो मैं वर्तमान में ले रहा हूं वह इस प्रकार है:

  1. यदि आप तत्काल कॉल करने वाले से अपेक्षा करते हैं कि वह catchज्यादातर समय अपवाद को हैंडल करे और अपना काम जारी रखे, तो शायद दूसरे रास्ते से, यह शायद रिटर्न टाइप का हिस्सा होना चाहिए। Optionalया OneOfयहाँ उपयोगी हो सकता है।
  2. यदि आप तत्काल कॉलर से अपेक्षा करते हैं कि वह अधिकांश समय अपवाद को न पकड़े, तो अपवाद को फेंक दें, मैन्युअल रूप से स्टैक को पास करने की शिथिलता को बचाने के लिए।
  3. यदि आप सुनिश्चित नहीं हैं कि तत्काल कॉलर क्या करने जा रहा है, तो शायद दोनों को पसंद करें, Parseऔर TryParse

13
F # Result;-) का प्रयोग करें
Astrinus

8
कुछ हद तक ऑफ-टॉपिक, लेकिन ध्यान दें कि जिस दृष्टिकोण को आप देख रहे हैं उसमें सामान्य भेद्यता है कि डेवलपर को ठीक से त्रुटि को सुनिश्चित करने का कोई तरीका नहीं है। निश्चित रूप से, टाइपिंग सिस्टम एक अनुस्मारक के रूप में कार्य कर सकता है, लेकिन आप किसी त्रुटि को संभालने में विफल होने के लिए प्रोग्राम को उड़ाने के डिफ़ॉल्ट को खो देते हैं, जिससे यह अधिक संभावना है कि आप कुछ अप्रत्याशित स्थिति में समाप्त हो जाते हैं। क्या अनुस्मारक उस डिफ़ॉल्ट के नुकसान के लायक है, हालांकि एक खुली बहस है। मुझे लगता है कि यह सोचना बेहतर है कि अपने सभी कोड को लिखना बेहतर है, अपवाद को किसी बिंदु पर समाप्त कर देगा; तो अनुस्मारक कम मूल्य है।
jpmc26

9
संबंधित लेख: अपवादों के चार "बाल्टी" पर एरिक लिपर्ट । उदाहरण जो वह बहिर्जात पर देता है, यह दर्शाता है कि ऐसे परिदृश्य हैं जहां आपको अपवादों से निपटना होगा, अर्थात FileNotFoundException
सोरेन डी। Pt Junus

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

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

जवाबों:


131

लेकिन अपने ग्राहक के सॉफ़्टवेयर को क्रैश करना अभी भी अच्छी बात नहीं है

यह निश्चित रूप से एक अच्छी बात है।

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

मैंने सुना है कि नियंत्रण प्रवाह के रूप में अपवादों को एक गंभीर एंटीपैटर्न माना जाता है

यह बिल्कुल सच है लेकिन यह अक्सर गलत समझा जाता है। जब उन्होंने अपवाद प्रणाली का आविष्कार किया तो वे डर गए कि वे संरचित प्रोग्रामिंग को तोड़ रहे हैं। संरचित प्रोग्रामिंग कारण है कि हम है for, while, until, break, और continueजब हम सभी की जरूरत है, यह सब करने के लिए, है goto

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

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

मौलिक रूप से अपवाद एक धारणा को खारिज करने के बारे में हैं। जब आप पूछते हैं कि किसी फ़ाइल को सहेजा जाए तो आप मान लेते हैं कि फ़ाइल को सहेजा जा सकता है। अपवाद जब आपको मिलता है तो यह नाम अवैध होने के बारे में नहीं हो सकता है, HD भरा हुआ है, या क्योंकि एक चूहे ने अपने डेटा केबल के माध्यम से पकड़ लिया है। आप उन सभी त्रुटियों को अलग-अलग तरीके से संभाल सकते हैं, आप उन सभी को उसी तरह से संभाल सकते हैं, या आप उन्हें सिस्टम को रोक सकते हैं। आपके कोड में एक खुशी का रास्ता है जहाँ आपकी मान्यताओं को सही होना चाहिए। एक रास्ता या कोई अन्य अपवाद आपको उस खुशहाल रास्ते से दूर ले जाता है। सख्ती से बोलना, हाँ, यह "प्रवाह नियंत्रण" का एक प्रकार है, लेकिन यह वह नहीं है जो वे आपको चेतावनी दे रहे थे। वे इस तरह बकवास कर रहे थे :

यहाँ छवि विवरण दर्ज करें

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

उससे कहीं अधिक महत्वपूर्ण है जो हमें भ्रमित नहीं कर रहा है। उपरोक्त कोड में अनंत लूप को स्पॉट करने में आपको कितना समय लगा?

त्रुटि कोड वापस न करें

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

OneOf

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

मुझे स्वयं सम्मेलन पसंद है। इसका एक सबसे अच्छा स्पष्टीकरण मुझे यहाँ मिला * :

यहाँ छवि विवरण दर्ज करें

लेकिन जितना मुझे यह पसंद है मैं अभी भी इसे अन्य सम्मेलनों के साथ मिश्रण नहीं करने जा रहा हूं। एक उठाओ और इसके साथ रहना। 1

1: जिससे मेरा मतलब है कि मुझे एक ही समय में एक से अधिक सम्मेलनों के बारे में नहीं सोचना चाहिए।


इसके बाद के विचार:

इस चर्चा से जो मैं वर्तमान में ले रहा हूं वह इस प्रकार है:

  1. यदि आप तत्काल कॉलर को सबसे अधिक अपवाद को पकड़ने और संभालने की उम्मीद करते हैं और अपना काम जारी रखते हैं, तो शायद दूसरे रास्ते से, यह संभवतः रिटर्न प्रकार का हिस्सा होना चाहिए। वैकल्पिक या वनऑफ यहां उपयोगी हो सकता है।
  2. यदि आप तत्काल कॉलर से अपेक्षा करते हैं कि वह अधिकांश समय अपवाद को न पकड़े, तो अपवाद को फेंक दें, मैन्युअल रूप से स्टैक को पास करने की शिथिलता को बचाने के लिए।
  3. यदि आप सुनिश्चित नहीं हैं कि तत्काल कॉलर क्या करने जा रहा है, तो शायद दोनों प्रदान करें, जैसे कि Parse और TryParse।

यह वास्तव में यह सरल नहीं है। मूलभूत बातों में से एक जो आपको समझने की जरूरत है वह है शून्य।

मई में कितने दिन बचे हैं? 0 (क्योंकि यह मई नहीं है। यह पहले से ही जून है)।

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

उदाहरण के लिए 2 :

IList<int> ParseAllTheInts(String s) { ... }

क्या आप किसी भी अच्छे कारण के बारे में सोच सकते हैं जिसे इस तरह से डिज़ाइन किया जाना चाहिए ताकि यह जानबूझकर कभी भी कुछ भी फेंक सके? लगता है कि जब कोई int पार्स नहीं किया जा सकता है तो आपको क्या मिलेगा? मुझे आपको बताने की जरूरत नहीं है।

यह एक अच्छे नाम का संकेत है। क्षमा करें, लेकिन TryParse एक अच्छे नाम का मेरा विचार नहीं है।

जब उत्तर एक ही समय में एक से अधिक चीजों का हो सकता है, तो हम अक्सर अपवाद को फेंकने से बचते हैं, लेकिन किसी कारण से यदि उत्तर एक ही चीज है या कुछ भी नहीं जो हम इस बात पर जोर देते हैं कि यह हमें एक चीज या फेंक देता है:

IList<Point> Intersection(Line a, Line b) { ... }

क्या समानांतर रेखाओं को वास्तव में यहां अपवाद की आवश्यकता है? क्या यह वास्तव में बुरा है कि अगर इस सूची में एक से अधिक बिंदु नहीं होंगे?

हो सकता है कि शब्दशः आप इसे नहीं ले सकते। यदि हां, तो यह एक दया है। लेकिन शायद मोनाड्स, कि एक मनमाना आकार की तरह Listनहीं है, आपको इसके बारे में बेहतर महसूस कराएगा ।

Maybe<Point> Intersection(Line a, Line b) { ... }

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

मुझे पता है, यह अजीब है। लेकिन यह एक नया उपकरण है (ठीक है, हमारे लिए)। इसलिए इसे थोड़ा समय दें। जब आप शिकंजा पर उनका उपयोग करना बंद कर देते हैं, तो हथौड़े अधिक मायने रखते हैं।


यदि आप मुझे लिप्त करेंगे, तो मैं इस टिप्पणी को संबोधित करना चाहूंगा:

कैसे आया कोई भी उत्तर स्पष्ट नहीं करता है कि या तो एक त्रुटि कोड नहीं है, और न ही OneOf है? वे मौलिक रूप से अलग हैं, और परिणामस्वरूप प्रश्न गलतफहमी पर आधारित लगता है। (हालांकि संशोधित रूप में यह अभी भी एक वैध प्रश्न है।) - कोनराड रूडोल्फ जून 4 `18 14:08 पर

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


9
क्या यह अधिक उचित नहीं होगा यदि लाल ट्रैक बक्से के नीचे था , इस प्रकार उनके माध्यम से नहीं चल रहा है?
फ्लैटर

4
तार्किक रूप से, आप सही हैं। हालांकि, इस विशेष आरेख में प्रत्येक बॉक्स एक मोनैडिक बाइंड ऑपरेशन का प्रतिनिधित्व करता है। बाइंड में लाल ट्रैक शामिल है (शायद बनाता है!)। मैं पूरी प्रस्तुति देखने की सलाह देता हूं। यह दिलचस्प है और स्कॉट एक महान वक्ता है।
गुस्सोर

7
मुझे लगता है कि एक GOTO के बजाय COMEFROM निर्देश जैसे अपवाद अधिक हैं , क्योंकि throwवास्तव में हमें पता नहीं है कि हम कहां
कूदेंगे

3
यदि आप सीमाओं को स्थापित कर सकते हैं, तो सम्मिश्रणों के मिश्रण में कुछ भी गलत नहीं है, यही सब कुछ है।
रॉबर्ट हार्वे

4
इस उत्तर का पूरा पहला भाग दृढ़ता से पढ़ता है जैसे कि आप उद्धृत वाक्य के बाद प्रश्न पढ़ना बंद कर देते हैं। प्रश्न स्वीकार करता है कि प्रोग्राम को क्रैश करना अपरिभाषित व्यवहार में आगे बढ़ने से बेहतर है: वे रन-टाइम क्रैश के विपरीत हैं जो निरंतर, अपरिभाषित निष्पादन के साथ नहीं हैं, बल्कि संकलन-समय की त्रुटियों के साथ हैं जो संभावित त्रुटि पर विचार किए बिना प्रोग्राम को बनाने से भी रोकते हैं। और इससे निपटना (जो कि दुर्घटना हो सकती है अगर कुछ और नहीं किया जा सकता है, लेकिन यह दुर्घटना होगी क्योंकि आप इसे चाहते हैं, इसलिए नहीं कि आप इसे भूल गए)।
केरेन

35

C # हास्केल नहीं है, और आपको C # समुदाय की विशेषज्ञ सहमति का पालन करना चाहिए। यदि आप इसके बजाय C # प्रोजेक्ट में हास्केल प्रथाओं का पालन करने का प्रयास करते हैं, तो आप अपनी टीम के बाकी सभी लोगों को अलग कर देंगे, और अंततः आपको शायद उन कारणों का पता चल जाएगा कि C # समुदाय चीजों को अलग तरीके से क्यों करता है। एक बड़ा कारण यह है कि सी # आसानी से भेदभाव वाली यूनियनों का समर्थन नहीं करता है।

मैंने सुना है कि नियंत्रण प्रवाह के रूप में अपवादों को एक गंभीर एंटीपेटर्न माना जाता है,

यह एक सार्वभौमिक रूप से स्वीकृत सत्य नहीं है। अपवादों का समर्थन करने वाली हर भाषा में चुनाव या तो एक अपवाद है (जो कॉलर को संभाल नहीं करने के लिए स्वतंत्र है) या कुछ यौगिक मूल्य (जिसे कॉलर MUST हैंडल) वापस करना है।

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


9
प्रचारित मठों के लिए कुछ नहीं करना चाहिए।
बसिलेव्स

23
@Basilevs कोड को पढ़ने योग्य रखते हुए, जो कि # नहीं है, को प्रचारित करने के लिए समर्थन की आवश्यकता होती है। आप या तो बार-बार निर्देश लौटाते हैं या लंबोदर की चेन।
सेबस्टियन रेडल

4
@ सेबैस्टियनरेडल लंबोदा सी # में ठीक लग रहे हैं।
बसिलेव्स

@Basilevs एक वाक्यविन्यास दृश्य से हाँ, लेकिन मुझे उनके प्रदर्शन के दृष्टिकोण से संदेह है कि वे कम आकर्षक हो सकते हैं।
छप्पर

5
आधुनिक C # में आप कुछ गति वापस पाने के लिए स्थानीय कार्यों का आंशिक रूप से उपयोग कर सकते हैं। किसी भी मामले में, अधिकांश व्यापारिक सॉफ्टवेयर IO द्वारा अन्य की तुलना में काफी अधिक धीमा है।
तुर्कसारमा

26

आप एक दिलचस्प समय पर C # पर आए हैं। अपेक्षाकृत हाल तक, भाषा अनिवार्य प्रोग्रामिंग स्पेस में दृढ़ता से बैठी थी। त्रुटियों को संप्रेषित करने के लिए अपवादों का उपयोग करना निश्चित रूप से आदर्श था। भाषा समर्थन की कमी (जैसे भेदभाव किए गए यूनियनों और पैटर्न मिलान के आसपास) से पीड़ित रिटर्न कोड का उपयोग करना। काफी हद तक, Microsoft से आधिकारिक मार्गदर्शन रिटर्न कोड से बचने और अपवादों का उपयोग करने के लिए था।

हमेशा इसके अपवाद रहे हैं, हालांकि, TryXXXतरीकों के रूप में , जो एक booleanसफलता परिणाम लौटाएगा और एक outपैरामीटर के माध्यम से दूसरे मूल्य के परिणाम की आपूर्ति करेगा । ये कार्यात्मक प्रोग्रामिंग में "कोशिश" पैटर्न के समान हैं, यह सहेजें कि परिणाम Maybe<T>रिटर्न पैरामीटर के बजाय एक बाहरी पैरामीटर के माध्यम से आता है ।

लेकिन चीजें बदल रही हैं। कार्यात्मक प्रोग्रामिंग और भी अधिक लोकप्रिय हो रही है और C # जैसी भाषाएं जवाब दे रही हैं। C # 7.0 ने भाषा के लिए कुछ बुनियादी पैटर्न मिलान विशेषताओं की शुरुआत की; C # 8 एक बहुत अधिक परिचय देगा, जिसमें एक स्विच अभिव्यक्ति, पुनरावर्ती पैटर्न आदि शामिल हैं। इसके साथ ही, C # के लिए "कार्यात्मक पुस्तकालयों" में वृद्धि हुई है , जैसे कि मेरी खुद की Succinc <T> लाइब्रेरी , जो विवेकशील यूनियनों के लिए भी समर्थन प्रदान करती है। ।

संयुक्त रूप से इन दो चीजों का मतलब है कि निम्नलिखित की तरह कोड धीरे-धीरे लोकप्रियता में बढ़ रहा है।

static Maybe<int> TryParseInt(string source) =>
    int.TryParse(source, out var result) ? new Some<int>(result) : none; 

public int GetNumberFromUser()
{
    Console.WriteLine("Please enter a number");
    while (true)
    {
        var userInput = Console.ReadLine();
        if (TryParseInt(userInput) is int value)
        {
            return value;
        }
        Console.WriteLine("That's not a valid number. Please try again");
    }
}

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

हम अभी तक यह कहने में नहीं हैं कि " त्रुटि कोड वापस न करें ।" पुरातन है और रिटायर होने की जरूरत है। लेकिन उस लक्ष्य की ओर सड़क नीचे मार्च अच्छी तरह से चल रहा है। इसलिए अपनी पिक लें: समलैंगिक परित्याग के साथ अपवादों को फेंकने के पुराने तरीकों से चिपके रहें यदि आप जिस तरह से चीजों को करना पसंद करते हैं; या एक नई दुनिया की खोज करना शुरू करें जहां कार्यात्मक भाषाओं से कन्वेंशन C # में अधिक लोकप्रिय हो रहे हैं।


22
यही कारण है कि मैं C # से नफरत करता हूं: :) वे एक बिल्ली की त्वचा के लिए तरीके जोड़ते रहते हैं, और निश्चित रूप से पुराने तरीके कभी नहीं जाते हैं। अंत में किसी भी चीज के लिए कोई कन्वेंशन नहीं है, एक पूर्णतावादी प्रोग्रामर घंटों तक बैठकर यह तय कर सकता है कि कौन सा तरीका "अच्छे" है, और एक नए प्रोग्रामर को दूसरों के कोड को पढ़ने में सक्षम होने से पहले सब कुछ सीखना होगा।
डबिन्स्की

24
@AleksandrDubinsky, आप सामान्य रूप से प्रोग्रामिंग भाषाओं के साथ एक मुख्य समस्या पर हिट करते हैं, न कि केवल C #। नई भाषाएं आधुनिक विचारों से निर्मित, दुबली, ताजा और भरी हुई हैं। और बहुत कम लोग उनका उपयोग करते हैं। समय के साथ, वे उपयोगकर्ताओं और नई सुविधाओं को प्राप्त करते हैं, पुरानी सुविधाओं के शीर्ष पर टकराते हैं जिन्हें हटाया नहीं जा सकता क्योंकि यह मौजूदा कोड को तोड़ देगा। फूला फूटता है। इसलिए लोक नई भाषाएं बनाते हैं जो दुबली, ताजा और आधुनिक विचारों से भरी होती हैं ...
डेविड अरनो

7
@AleksandrDubinsky आप इसे नफरत नहीं करते जब वे 1960 के दशक की सुविधाओं को जोड़ते हैं।
ctrl-alt-delor

6
@AleksandrDubinsky हाँ। क्योंकि जावा ने एक बार (जेनेरिक) एक चीज़ को जोड़ने की कोशिश की , वे विफल हो गए हैं, हमें अब उस भयानक गंदगी के साथ रहना होगा जिसके परिणामस्वरूप उन्होंने सबक सीखा है और कुछ भी जोड़ना छोड़ दिया है
:)

3
@Agent_L: आपको पता है कि जावा का जोड़ा java.util.Stream(एक आधा assed IEnumerable-alike) और लैम्ब्डा अब, सही है? :)
cHao

5

मुझे लगता है कि त्रुटियों को वापस करने के लिए एक DU का उपयोग करना पूरी तरह से उचित है, लेकिन फिर मैं कहूंगा कि जैसा कि मैंने OneOf :) लिखा है, लेकिन मैं कहूंगा कि वैसे भी, जैसा कि F # आदि में एक आम बात है (जैसे कि परिणाम प्रकार, जैसा कि दूसरों द्वारा उल्लेख किया गया है) )।

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

यहाँ परियोजना पृष्ठ से उदाहरण दिया गया है।

public OneOf<User, InvalidName, NameTaken> CreateUser(string username)
{
    if (!IsValid(username)) return new InvalidName();
    var user = _repo.FindByUsername(username);
    if(user != null) return new NameTaken();
    var user = new User(username);
    _repo.Save(user);
    return user;
}

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

किस हद तक OneOf c # में मुहावरेदार है, यह एक और सवाल है। वाक्यविन्यास वैध और यथोचित सहज है। DU और रेल-उन्मुख-प्रोग्रामिंग अच्छी तरह से ज्ञात अवधारणाएं हैं।

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


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

हाँ - और एक आसान तरीका प्रदान करता है जो कॉलर में संपूर्ण मिलान करता है, जो कि वंशानुक्रम आधारित परिणाम पदानुक्रम का उपयोग करना संभव नहीं है।
mcintyre321

4

OneOfजावा में जाँच किए गए अपवादों के बराबर है। कुछ अंतर हैं:

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

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

OneOf और चेक किए गए अपवाद में एक महत्वपूर्ण "सुविधा" है:

  • वे दोनों आपको कॉल स्टैक में हर जगह उन्हें संभालने के लिए मजबूर करते हैं

यह आपके डर को रोकता है

C # में, अपवादों को अनदेखा करना एक संकलन त्रुटि पैदा नहीं करता है, और यदि वे पकड़े नहीं जाते हैं तो वे सिर्फ बुलबुला बनाते हैं और आपके प्रोग्राम को क्रैश करते हैं।

लेकिन जैसा कि पहले ही कहा गया है, यह डर तर्कहीन है। मूल रूप से, आपके कार्यक्रम में आमतौर पर एक ही जगह होती है, जहाँ आपको हर चीज को पकड़ने की जरूरत होती है (संभावना है कि आप इसे पहले से ही कर रहे फ्रेमवर्क का उपयोग करेंगे)। जैसा कि आप और आपकी टीम आमतौर पर कार्यक्रम पर काम करते हुए सप्ताह या साल बिताते हैं, आप इसे नहीं भूलेंगे, क्या आप?

आग्नेय अपवादों का बड़ा लाभ यह है कि उन्हें जहाँ भी आप संभालना चाहते हैं, उन्हें संभाला जा सकता है, बल्कि तब हर जगह स्टैक ट्रेस में। यह बॉयलरप्लेट के टन को समाप्त करता है (बस कुछ जावा कोड को "थ्रो ...." या रैपिंग अपवाद घोषित करते हुए देखें) और यह आपके कोड को कम बगिया भी बनाता है: जैसा कि कोई भी तरीका फेंक सकता है, आपको इसके बारे में पता होना चाहिए। सौभाग्य से, सही कार्रवाई आम तौर पर कुछ भी नहीं कर रही है , अर्थात, इसे एक ऐसी जगह तक बुलबुला देना जहां इसे उचित तरीके से संभाला जा सके।


+1 लेकिन OneOf साइड इफेक्ट्स के साथ काम क्यों नहीं करता है? (मुझे लगता है कि यह इसलिए है क्योंकि यह एक चेक पास करेगा यदि आप रिटर्न वैल्यू असाइन नहीं करते हैं, लेकिन जैसा कि मैं वनऑफ को नहीं जानता हूं, न ही बहुत सी # मुझे यकीन नहीं है - स्पष्टीकरण आपके उत्तर को बेहतर
बनाएगा

1
आप बनाने से त्रुटि आई वस्तु उपयोगी जानकारी जैसे होते हैं द्वारा oneof साथ त्रुटि की जानकारी लौट सकते हैं OneOf<SomeSuccess, SomeErrorInfo>जहां SomeErrorInfoत्रुटि के विवरण प्रदान करता है।
mcintyre321

@dcorking संपादित किया गया। निश्चित रूप से, यदि आपने रिटर्न वैल्यू को नजरअंदाज किया है, तो आप जानते हैं कि क्या समस्या हुई। यदि आप एक शुद्ध कार्य के साथ ऐसा करते हैं, तो यह ठीक है (आप सिर्फ समय बर्बाद करते हैं)।
मआर्टिनस

2
@ mcintyre321 ज़रूर, आप जानकारी जोड़ सकते हैं, लेकिन आपको इसे मैन्युअल रूप से करना होगा और यह आलस्य और भूल के अधीन है। मुझे लगता है, अधिक जटिल मामलों में, एक स्टैक ट्रेस अधिक सहायक है।
मआर्टिनस

4

"साधारण" अपवादों (जैसे फ़ाइल नहीं मिला आदि) को संभालने के लिए अपवादों के बजाय OneOf का उपयोग करना एक उचित दृष्टिकोण है या यह भयानक अभ्यास है?

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

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

गैर-रोके जाने योग्य, अक्सर और पुनर्प्राप्त करने योग्य त्रुटियां वे हैं जो वास्तव में कॉल साइट पर निपटाए जाने की आवश्यकता है। वे कॉल करने वाले को उनसे भिड़ने के लिए मजबूर करने का औचित्य साबित करते हैं। जावा में, मैं उन्हें अपवादों की जाँच करता हूँ, और एक समान प्रभाव उन्हें Try*विधियाँ बनाने या भेदभावपूर्ण संघ को वापस करने से प्राप्त होता है । जब किसी फंक्शन का रिटर्न वैल्यू होता है तो डिस्क्रिमिनेटेड यूनियनें विशेष रूप से अच्छी होती हैं। वे लौटने का एक अधिक परिष्कृत संस्करण हैं nulltry/catchब्लॉक का सिंटैक्स बढ़िया नहीं है (बहुत सारे ब्रैकेट), जिससे विकल्प बेहतर दिखते हैं। इसके अलावा, अपवाद थोड़ा धीमा है क्योंकि वे स्टैक के निशान को रिकॉर्ड करते हैं।

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

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

मेरे अनुभव में, कॉल करने वाले को त्रुटि की स्थिति का सामना करने के लिए मजबूर करना ठीक है जब त्रुटियां गैर-रोकथाम योग्य, अक्सर और पुनर्प्राप्त करने योग्य होती हैं, लेकिन यह बहुत कष्टप्रद होता है जब कॉल करने वाले को हुप्स के माध्यम से कूदने के लिए मजबूर किया जाता है जब उन्हें ज़रूरत नहीं होती है या वे चाहते हैं । ऐसा इसलिए हो सकता है क्योंकि कॉलर जानता है कि त्रुटि नहीं होगी, या क्योंकि वे (अभी तक) कोड को लचीला नहीं बनाना चाहते हैं। जावा में, यह जाँच किए गए अपवादों के बार-बार उपयोग करने और वैकल्पिक लौटने (जो शायद के समान है और हाल ही में बहुत विवाद के बीच पेश किया गया था) के खिलाफ गुस्से को स्पष्ट करता है। जब संदेह हो, तो अपवादों को फेंक दें और फोन करने वाले को यह तय करने दें कि वे उन्हें कैसे संभालना चाहते हैं।

अंत में, ध्यान रखें कि त्रुटि की स्थिति के बारे में सबसे महत्वपूर्ण बात, किसी भी अन्य विचार से ऊपर, जैसे कि उन्हें कैसे संकेत दिया जाता है, पूरी तरह से दस्तावेज़ करना है


2

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

OneOf एक त्रुटि कोड नहीं है, यह एक मोनाड की तरह अधिक है

जिस तरह से इसका उपयोग किया जाता है, OneOf<Value, Error1, Error2>यह एक कंटेनर है जो या तो वास्तविक परिणाम या कुछ त्रुटि स्थिति का प्रतिनिधित्व करता है। यह एक तरह से है Optional, सिवाय इसके कि जब कोई मूल्य मौजूद नहीं है, तो यह अधिक विवरण प्रदान कर सकता है कि क्यों है।

त्रुटि कोड के साथ मुख्य समस्या यह है कि आप उन्हें जांचना भूल जाते हैं। लेकिन यहां, आप सचमुच त्रुटियों की जांच किए बिना परिणाम तक नहीं पहुंच सकते।

एकमात्र समस्या यह है कि जब आप परिणाम की परवाह नहीं करते हैं। OneOf के प्रलेखन से उदाहरण देता है:

public OneOf<User, InvalidName, NameTaken> CreateUser(string username) { ... }

... और फिर वे प्रत्येक परिणाम के लिए अलग-अलग HTTP प्रतिक्रियाएं बनाते हैं, जो अपवादों का उपयोग करने से बहुत बेहतर है। लेकिन अगर आप विधि को इस तरह कहते हैं।

public void CreateUserButtonClick(String username) {
    UserManager.CreateUser(string username)
}

तो आप करते हैं एक समस्या है और अपवादों बेहतर विकल्प होगा। रेल saveबनाम की तुलना करें save!


1

एक बात जिस पर आपको विचार करने की आवश्यकता है वह यह है कि C # में कोड आमतौर पर शुद्ध नहीं है। साइड-इफेक्ट्स से भरे कोड-बेस में, और एक कंपाइलर के साथ, जो इस बात की परवाह नहीं करता है कि आप किसी फ़ंक्शन के रिटर्न वैल्यू के साथ क्या करते हैं, आपके दृष्टिकोण से आपको काफी दुःख हो सकता है। उदाहरण के लिए, यदि आपके पास कोई ऐसा तरीका है जो किसी फ़ाइल को हटा देता है, तो आप यह सुनिश्चित करना चाहते हैं कि विधि विफल होने पर एप्लिकेशन नोटिफ़िकेशन करें, भले ही "खुश मार्ग पर" किसी भी त्रुटि कोड की जांच करने का कोई कारण नहीं है। यह उन कार्यात्मक भाषाओं से काफी अंतर है जिनकी आपको स्पष्ट रूप से वापसी मूल्यों को अनदेखा करने की आवश्यकता है जो आप उपयोग नहीं कर रहे हैं। C # में, रिटर्न मानों की हमेशा अनदेखी की जाती है (संपत्ति अपवाद IIRC होने का एकमात्र अपवाद)।

MSDN आपको "त्रुटि कोड वापस नहीं करने" के लिए कहता है, यही कारण है - कोई भी आपको त्रुटि कोड पढ़ने के लिए मजबूर नहीं करता है । संकलक आपकी बिल्कुल मदद नहीं करता है। हालाँकि, यदि आपका फ़ंक्शन साइड-इफ़ेक्ट फ्री है, तो आप सुरक्षित रूप से कुछ का उपयोग कर सकते हैं Either- बिंदु यह है कि भले ही आप त्रुटि परिणाम (यदि कोई हो) को अनदेखा करते हैं, तो आप केवल ऐसा कर सकते हैं यदि आप "उचित परिणाम" का उपयोग नहीं करते हैं या तो। कुछ तरीके हैं कि आप इसे कैसे पूरा कर सकते हैं - उदाहरण के लिए, आप केवल सफलता और त्रुटि मामलों को संभालने के लिए एक प्रतिनिधि को पास करके "रीडिंग" मान की अनुमति दे सकते हैं, और आप आसानी से रेलवे ओरिएंटेड प्रोग्रामिंग जैसे दृष्टिकोणों के साथ जोड़ सकते हैं (यह करता है) काम ठीक सी # में)।

int.TryParseबीच में कहीं है। यह शुद्ध है। यह परिभाषित करता है कि दो परिणामों के मूल्य हर समय क्या हैं - इसलिए आप जानते हैं कि यदि वापसी मूल्य है false, तो आउटपुट पैरामीटर को सेट किया जाएगा 0। यह अभी भी आपको रिटर्न मान की जाँच किए बिना आउटपुट पैरामीटर का उपयोग करने से नहीं रोकता है, लेकिन कम से कम आप गारंटी देते हैं कि फ़ंक्शन विफल होने पर भी परिणाम क्या है।

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


0

सही कथन अपवादों के लिए त्रुटि कोड का उपयोग नहीं करेंगे ! और गैर-अपवादों के लिए अपवादों का उपयोग न करें।

अगर कुछ ऐसा होता है कि आपका कोड पुनर्प्राप्त नहीं कर सकता (यानी यह काम करता है), तो यह एक अपवाद है। ऐसा कुछ भी नहीं है कि आपका तत्काल कोड एक त्रुटि कोड के साथ होगा, सिवाय इसके कि इसे लॉग इन करने के लिए या शायद किसी तरह उपयोगकर्ता को कोड प्रदान करें। हालाँकि यह वास्तव में अपवाद हैं - वे सभी सौंपने के साथ व्यवहार करते हैं और वास्तव में क्या हुआ, इसका विश्लेषण करने में मदद करते हैं।

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

(ध्यान दें कि मैं C # में बहुत अनुभवी नहीं हूं, लेकिन मेरा जवाब सामान्य मामलों में होना चाहिए कि अपवाद क्या हैं, के वैचारिक स्तर के आधार पर।)


7
मैं मूल रूप से इस जवाब के आधार से असहमत हूं। यदि भाषा डिजाइनरों ने पुनर्प्राप्ति योग्य त्रुटियों के लिए उपयोग किए जाने वाले अपवादों का इरादा नहीं किया है, तो catchकीवर्ड मौजूद नहीं होगा। और जब से हम एक सी # संदर्भ में बात कर रहे हैं, यह ध्यान देने योग्य है कि यहां पर मौजूद दर्शन .NET फ्रेमवर्क द्वारा अनुसरण नहीं किए जाते हैं; शायद "अमान्य इनपुट जिसे आप संभाल सकते हैं" का सबसे सरल कल्पनाशील उदाहरण है गैर-संख्या में उपयोगकर्ता टाइपिंग एक ऐसे क्षेत्र में जहां एक संख्या अपेक्षित है ... और int.Parseएक अपवाद फेंकता है।
मार्क अमेरी

@MarkAmery int.Parse के लिए यह ऐसा कुछ भी नहीं है जो न ही इससे उबर सकता है और न ही यह उम्मीद करेगा। कैच क्लॉज का उपयोग आमतौर पर बाहरी दृश्य से पूर्ण विफलता से बचने के लिए किया जाता है, यह उपयोगकर्ता को नए डेटाबेस क्रेडेंशियल या इस तरह के लिए नहीं पूछेगा, यह प्रोग्राम क्रैश होने से बचाएगा। यह एक तकनीकी विफलता है एक आवेदन नियंत्रण प्रवाह नहीं।
फ्रैंक हॉपकिंस

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

@Darkwing "आप उन मामलों को त्रुटि कोड या किसी अन्य आर्किटेक्चर के साथ हैंडल करने के लिए स्वतंत्र महसूस कर सकते हैं"। हां, आप ऐसा करने के लिए स्वतंत्र हैं। हालाँकि, ऐसा करने के लिए आपको .NET से कोई समर्थन नहीं मिलता है, क्योंकि .NET CL स्वयं त्रुटि कोड के बजाय अपवाद का उपयोग करता है। इसलिए न केवल आप बहुत से मामलों में .NET अपवादों को पकड़ने के लिए मजबूर हो रहे हैं और अपवाद बबल को छोड़ देने के बजाय अपने संबंधित त्रुटि कोड को वापस कर रहे हैं, आप अपनी टीम के अन्य लोगों को भी एक अन्य त्रुटि हैंडलिंग अवधारणा में मजबूर कर रहे हैं जिसका उन्हें उपयोग करना है अपवादों के साथ समानांतर में, मानक त्रुटि हैंडलिंग अवधारणा।
अलेक्जेंडर

-2

यह एक 'भयानक आइडिया' है।

यह भयानक है, क्योंकि कम से कम .net में, आपके पास संभावित अपवादों की विस्तृत सूची नहीं है। कोई भी कोड संभवतः किसी भी अपवाद को फेंक सकता है। खासकर यदि आप OOP कर रहे हैं और घोषित प्रकार के बजाय उप प्रकार पर ओवरराइड तरीके कह सकते हैं

इसलिए आपको सभी तरीकों और कार्यों को बदलना होगा OneOf<Exception, ReturnType>, फिर यदि आप विभिन्न अपवाद प्रकारों को संभालना चाहते हैं, तो आपको टाइप If(exception is FileNotFoundException)आदि की जांच करनी होगी

try catch के बराबर है OneOf<Exception, ReturnType>

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

मुझे पता है कि आप लौटने का प्रस्ताव रखते हैं OneOf<ErrorEnum, ReturnType>लेकिन मुझे लगता है कि यह कुछ अंतर के बिना एक अंतर है।

आप अपवाद द्वारा रिटर्न कोड, अपेक्षित अपवाद और ब्रांचिंग का संयोजन कर रहे हैं। लेकिन समग्र प्रभाव समान है।


2
'सामान्य' अपवाद भी एक भयानक विचार है। सुराग नाम में है
इवान

4
मैं वापस लौटने का प्रस्ताव नहीं कर रहा हूं Exception
क्लिंटन

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