अपवाद बनाम खाली परिणाम सेट जब इनपुट तकनीकी रूप से मान्य होते हैं, लेकिन असंतोषजनक


108

मैं सार्वजनिक रिलीज के लिए एक पुस्तकालय विकसित कर रहा हूं। इसमें ऑब्जेक्ट्स के सेट पर काम करने के लिए विभिन्न तरीके हैं - सेट को नए रूपों में बनाना, निरीक्षण करना, विभाजन करना और प्रोजेक्ट करना। यदि यह प्रासंगिक है, तो यह एक सी # क्लास लाइब्रेरी है, जिसमें लाइनक्यू-स्टाइल एक्सटेंशन है IEnumerable, जिसे नूगेट पैकेज के रूप में जारी किया जाना है।

इस लाइब्रेरी के कुछ तरीकों को असंतोषजनक इनपुट पैरामीटर दिए जा सकते हैं। उदाहरण के लिए, कॉम्बिनेटरिक विधियों में, n आइटम के सभी सेट उत्पन्न करने के लिए एक विधि है जिसका निर्माण m आइटम के स्रोत सेट से किया जा सकता है । उदाहरण के लिए, सेट दिया गया:

1, 2, 3, 4, 5

और 2 के संयोजन के लिए पूछना होगा:

1, 2
1, 3
1, 4
आदि ...
5, 3
5, 4

अब, यह स्पष्ट रूप से कुछ ऐसा करने के लिए कहा जा सकता है, जैसे कि इसे 3 आइटम का एक सेट देना और फिर विकल्प सेट करते समय 4 वस्तुओं के संयोजन के लिए पूछना, यह कहता है कि यह केवल प्रत्येक आइटम का उपयोग कर सकता है।

इस परिदृश्य में, प्रत्येक पैरामीटर व्यक्तिगत रूप से मान्य है:

  • स्रोत संग्रह शून्य नहीं है, और इसमें आइटम नहीं हैं
  • संयोजनों का अनुरोधित आकार एक सकारात्मक गैर-पूर्णांक पूर्णांक है
  • अनुरोधित मोड (प्रत्येक आइटम का केवल एक बार उपयोग करें) एक वैध विकल्प है

हालांकि, मापदंडों की स्थिति जब एक साथ ली जाती है तो समस्याएं पैदा होती हैं।

इस परिदृश्य में, क्या आप किसी अपवाद (जैसे। InvalidOperationException) को फेंकने के लिए विधि की अपेक्षा करेंगे या एक खाली संग्रह लौटाएंगे? या तो मुझे मान्य लगता है:

  • आप के संयोजन का उत्पादन नहीं कर सकते हैं n का एक सेट से आइटम मीटर आइटम जहां n> मी यदि आप केवल एक बार प्रत्येक आइटम उपयोग करने की अनुमति है, इसलिए इस ऑपरेशन असंभव समझा जा सकता है, इसलिए InvalidOperationException
  • आकार के संयोजन के सेट n कि से उत्पादन किया जा सकता मीटर जब आइटम n> मी एक खाली सेट है, कोई संयोजन निर्मित नहीं किया जा सकता है।

खाली सेट के लिए तर्क

मेरी पहली चिंता यह है कि जब आप डेटासेट्स से अनजान आकार में हो सकते हैं, तो एक अपवाद विधियों के मुहावरेदार LINQ- शैली को परिभाषित करने से रोकता है। दूसरे शब्दों में, आप कुछ इस तरह से करना चाह सकते हैं:

var result = someInputSet
    .CombinationsOf(4, CombinationsGenerationMode.Distinct)
    .Select(combo => /* do some operation to a combination */)
    .ToList();

यदि आपका इनपुट सेट परिवर्तनशील आकार का है, तो इस कोड का व्यवहार अप्रत्याशित है। यदि 4 से कम तत्वों के .CombinationsOf()अपवाद को फेंकता है someInputSet, तो यह कोड कभी-कभी कुछ पूर्व-जाँच के बिना रनटाइम पर विफल हो जाएगा । उपरोक्त उदाहरण में यह जाँच तुच्छ है, लेकिन यदि आप इसे LINQ की लंबी श्रृंखला से आधा नीचे बुला रहे हैं तो यह थकाऊ हो सकता है। यदि यह एक खाली सेट लौटाता है, तो resultखाली होगा, जिसे आप पूरी तरह से खुश हो सकते हैं।

एक अपवाद के लिए तर्क

मेरी दूसरी चिंता यह है कि एक खाली सेट लौटाने से समस्याएँ छिप सकती हैं - यदि आप इस विधि को LINQ की एक श्रृंखला से आधा कर रहे हैं और यह चुपचाप एक खाली सेट लौटाता है, तो आप कुछ चरणों में बाद में भाग सकते हैं, या अपने आप को एक खाली के साथ पा सकते हैं। परिणाम सेट, और यह स्पष्ट नहीं हो सकता है कि यह कैसे हुआ कि आपको निश्चित रूप से इनपुट सेट में कुछ मिला।

आप क्या उम्मीद करेंगे, और इसके लिए आपका क्या तर्क है?


66
चूंकि खाली सेट गणितीय रूप से सही है, संभावना है कि जब आप इसे प्राप्त करते हैं तो यह वास्तव में वही होता है जो आप चाहते हैं। गणितीय परिभाषाएँ और रूढ़ियाँ आम तौर पर स्थिरता और सुविधा के लिए चुनी जाती हैं ताकि चीजें उनके साथ काम करें।
17

5
@asmeurer वे चुने गए हैं ताकि प्रमेय सुसंगत और सुविधाजनक हों। वे प्रोग्रामिंग को आसान बनाने के लिए नहीं चुने गए हैं। (यह कभी-कभी एक साइड बेनिफिट होता है, लेकिन कभी-कभी वे प्रोग्रामिंग को बहुत कठिन बना देते हैं।)
jpmc26

7
@ jpmc26 "वे चुने गए हैं ताकि प्रमेय सुसंगत और सुविधाजनक हों" - यह सुनिश्चित करना कि आपका कार्यक्रम हमेशा अपेक्षित रूप से काम करता है, अनिवार्य रूप से एक प्रमेय साबित करने के बराबर है।
आर्टेम

2
@ jpmc26 मुझे नहीं मिलता कि आपने कार्यात्मक प्रोग्रामिंग का उल्लेख क्यों किया। अनिवार्य कार्यक्रमों के लिए शुद्धता साबित करना हमेशा संभव होता है, और अनौपचारिक रूप से भी किया जा सकता है - बस थोड़ा सोचें और जब आप अपना कार्यक्रम लिखें तो सामान्य गणितीय अर्थ का उपयोग करें, और आप कम समय परीक्षण करेंगे। एक के नमूने पर सांख्यिकीय रूप से सिद्ध ;-)
आर्टेम

5
@DmitryGrigoryev 1/0 अपरिभाषित के रूप में अनंत के रूप में 1/0 की तुलना में गणितीय रूप से अधिक सही है।
asmeurer

जवाबों:


145

एक खाली सेट लौटें

मैं एक खाली सेट की उम्मीद करूंगा क्योंकि:

3 के सेट से 4 संख्याओं के 0 संयोजन हैं जब मैं केवल एक बार प्रत्येक संख्या का उपयोग कर सकता हूं


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

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

11
वास्तव में आप नहीं जानते कि यह उपयोगकर्ता की नज़र में कोई त्रुटि है। खाली सेट कुछ ऐसा है जिसे उपयोगकर्ता को जांचना चाहिए, यदि आवश्यक हो। if (result.Any ()) DoSomething (result.First ()); अन्यथा DoSomethingElse (); प्रयास {result.first ()। dosomething ();} कैच {DoSomethingEse ();};}
Guran

4
@TripeHound अंत में यह निर्णय लिया गया है: विकास के प्रयास, कार्यक्रम प्रदर्शन और कार्यक्रम प्रवाह की सादगी।
anaximander

6
@Darthfett मौजूदा LINQ एक्सटेंशन विधि से इसकी तुलना करने का प्रयास करें: कहां ()। यदि मेरे पास कोई खंड है: कहां (x => 1 == 2) मुझे कोई अपवाद नहीं मिला, तो मुझे एक खाली सेट मिलेगा।
नेकोरस

79

जब संदेह हो, तो किसी और से पूछें।

आपके उदाहरण समारोह में पायथन में एक बहुत ही समान है itertools.combinations:। आइए देखें कि यह कैसे काम करता है:

>>> import itertools
>>> input = [1, 2, 3, 4, 5]
>>> list(itertools.combinations(input, 2))
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
>>> list(itertools.combinations(input, 5))
[(1, 2, 3, 4, 5)]
>>> list(itertools.combinations(input, 6))
[]

और यह मुझे पूरी तरह से ठीक लगता है। मैं एक परिणाम की उम्मीद कर रहा था कि मैं इसे खत्म कर सकता हूं और मुझे एक मिल गया है।

लेकिन, जाहिर है, अगर आप कुछ बेवकूफ पूछना चाहते थे:

>>> list(itertools.combinations(input, -1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: r must be non-negative

तो मैं कहूंगा, अगर आपके सभी पैरामीटर मान्य हैं, लेकिन परिणाम एक खाली सेट है, एक खाली सेट लौटाते हैं, तो आप केवल ऐसा नहीं कर रहे हैं।


जैसा कि @Bakuriu द्वारा टिप्पणियों में कहा गया है , यह भी एक SQLक्वेरी की तरह ही है SELECT <columns> FROM <table> WHERE <conditions>। जब तक <columns>, <table>, <conditions>अच्छी तरह का गठन किया और मौजूदा नामों का उल्लेख गठन कर रहे हैं, तो आप की स्थिति है कि एक दूसरे को बाहर निकालने के का एक सेट बना सकते हैं। परिणामी क्वेरी सिर्फ फेंकने के बजाय कोई पंक्तियाँ नहीं लाएगी InvalidConditionsError


4
डाउनवोट किया गया है क्योंकि यह C # / Linq भाषा स्थान में मुहावरेदार नहीं है (देखें कि भाषा में समान समस्याओं से कैसे निपटना है, इसके लिए sbecker का उत्तर देखें)। अगर यह एक पायथन सवाल था, तो यह मेरे से एक +1 होगा।
जेम्स स्नेल

32
@JamesSnell मैं मुश्किल से देख रहा हूं कि यह आउट-ऑफ-बाउंड्स समस्या से कैसे संबंधित है। हम तत्वों को अनुक्रमित करने के लिए उन्हें फिर से नहीं उठा रहे हैं, हम nसंग्रह में तत्वों को चुन रहे हैं जिस तरह से हम उन्हें चुन सकते हैं। यदि किसी बिंदु पर उन्हें उठाते समय कोई तत्व नहीं बचा है, तो nउक्त संग्रह से तत्वों को चुनने का कोई (0) तरीका नहीं है ।
मथियास एटिंगर

1
फिर भी, पायथन C # प्रश्नों के लिए एक अच्छा आभूषण नहीं है: उदाहरण के लिए C # अनुमति देगा 1.0 / 0, पायथन नहीं होगा।
दिमित्री ग्रिगोरीव

2
@MathiasEttinger पायथन के अपवादों का उपयोग कैसे और कब करना है, इसके लिए C # के सिरों पर बहुत भिन्नता है, इसलिए पायथन मॉड्यूल से एक दिशानिर्देश के रूप में व्यवहार का उपयोग करना C # के लिए अच्छा मीट्रिक नहीं है।
एंट पी

2
अजगर को चुनने के बजाय हम एसक्यूएल चुन सकते हैं। क्या परिणाम सेट खाली होने पर एक टेबल पर एक अच्छी तरह से बनाई गई SELECT क्वेरी एक अपवाद उत्पन्न करती है? (बिगाड़ने: नहीं!)। एक क्वेरी की "अच्छी तरह से गठित" केवल क्वेरी पर ही निर्भर करती है और कुछ मेटाडेटा (जैसे कि तालिका मौजूद है और इस क्षेत्र में है (इस प्रकार के साथ)?) एक बार जब क्वेरी अच्छी तरह से बनती है और आप इसे निष्पादित करते हैं तो आप या तो उम्मीद करते हैं कि आप (संभवतः खाली) वैध परिणाम या एक अपवाद क्योंकि "सर्वर" में एक समस्या थी (उदाहरण के लिए db सर्वर नीचे चला गया या कुछ और)।
बाकुरू

72

आम आदमी की शर्तों में:

  • यदि कोई त्रुटि है, तो आपको एक अपवाद उठाना चाहिए। इसमें एक ही जंजीर कॉल के बजाय चरणों में चीजें करना शामिल हो सकता है ताकि यह पता चल सके कि त्रुटि कहां हुई थी।
  • यदि कोई त्रुटि नहीं है, लेकिन परिणामी सेट खाली है, तो अपवाद न उठाएं, खाली सेट लौटाएं। एक खाली सेट एक वैध सेट है।

23
+1, 0 पूरी तरह से मान्य है, और वास्तव में अत्यंत महत्वपूर्ण संख्या है। ऐसे कई मामले हैं जहां एक क्वेरी शून्य हिट को वैध रूप से वापस कर सकती है जो एक अपवाद को बढ़ाकर अत्यधिक कष्टप्रद होगा।
किलन फ़ॉथ

19
अच्छी सलाह, लेकिन क्या आपका जवाब स्पष्ट है?
इवान

54
मैं अभी भी समझदार नहीं हूँ, क्योंकि यह उत्तर बताता है कि ओपी को throwएक खाली सेट वापस करना चाहिए या वापस करना चाहिए ...
जेम्स स्नेल

7
आपका उत्तर कहता है कि मैं या तो कर सकता हूं, इस पर निर्भर करता है कि क्या कोई त्रुटि है, लेकिन आप उल्लेख नहीं करते हैं कि क्या आप उदाहरण के परिदृश्य को एक त्रुटि मानते हैं। ऊपर की टिप्पणी में आप कहते हैं कि मुझे एक खाली सेट लौटना चाहिए "अगर कोई समस्या नहीं है", लेकिन फिर से, असंतोषजनक परिस्थितियों को एक समस्या माना जा सकता है, और आप यह कहते हैं कि मुझे अपवाद नहीं उठाना चाहिए जब मुझे चाहिए। तो मुझे क्या करना चाहिए?
Anaximander

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

53

मैं इवान के जवाब से सहमत हूं लेकिन एक विशिष्ट तर्क जोड़ना चाहता हूं।

आप गणितीय कार्यों से निपट रहे हैं, इसलिए समान गणितीय परिभाषाओं के साथ रहना एक अच्छी सलाह हो सकती है। एक गणितीय दृष्टिकोण से की संख्या आर एक की -sets n सेट (यानी nCr ) अच्छी तरह से सभी आर के लिए परिभाषित किया गया है> n> = 0. यह शून्य है। इसलिए एक खाली सेट लौटाना एक गणितीय दृष्टिकोण से अपेक्षित मामला होगा।


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

1
इवांस के जवाब से बहुत बेहतर यह गणितीय अभ्यास का हवाला देता है। +1
user949300

24

मुझे यह निर्धारित करने का एक अच्छा तरीका है कि क्या अपवाद का उपयोग करना है, लेन-देन में शामिल लोगों की कल्पना करना है।

उदाहरण के रूप में फ़ाइल की सामग्री प्राप्त करना:

  1. कृपया मुझे फ़ाइल की सामग्री लाएँ, "मौजूद नहीं है।"

    ए। "यहाँ सामग्री है: पात्रों का एक खाली संग्रह"

    ख। "एर्म, एक समस्या है, वह फ़ाइल मौजूद नहीं है। मुझे नहीं पता कि क्या करना है!"

  2. कृपया मुझे फ़ाइल की सामग्री लाएँ, "मौजूद है लेकिन खाली है।"

    ए। "यहाँ सामग्री है: पात्रों का एक खाली संग्रह"

    ख। "एर्म, एक समस्या है, इस फाइल में कुछ भी नहीं है। मुझे नहीं पता कि क्या करना है!"

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

तो अपने दृष्टिकोण के लिए एक ही दृष्टिकोण लागू:

  1. कृपया मुझे सभी 4 आइटमों के सभी संयोजन दें {1, 2, 3}

    ए। कोई भी नहीं है, यहाँ एक खाली सेट है।

    ख। एक समस्या है, मुझे नहीं पता कि क्या करना है।

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

यदि कोई खाली मान लौटाता है तो समस्या का nullसामना करना पड़ता है (उदाहरण के लिए एक लापता फ़ाइल, a ), तो इसके बजाय आम तौर पर एक अपवाद का उपयोग किया जाना चाहिए (जब तक कि आपकी चुनी हुई भाषा option/maybeप्रकारों का समर्थन नहीं करती है , तब वे कभी-कभी अधिक समझ में आते हैं)। अन्यथा, खाली मान लौटाने से लागत सरल हो जाएगी और कम से कम विस्मय के सिद्धांत के साथ बेहतर अनुपालन होगा।


4
यह सलाह अच्छी है, लेकिन इस मामले पर लागू नहीं होती है। एक बेहतर उदाहरण: 30 के कितने दिन बाद: थॉट ऑफ दि ?: 1 कितने दिनों के बाद 30: वें दिन का ?: 0 30 के कितने दिन बाद: थ्यूप मेड्यूपर का ?: अपवाद 30 पर कितने काम के घंटे? :
पंद्रहवें दिन

9

जैसा कि यह एक सामान्य उद्देश्य पुस्तकालय के लिए है मेरी वृत्ति अंत उपयोगकर्ता को चुनने देंगी

बहुत कुछ हमारे पास उपलब्ध है Parse()और हमारे पास TryParse()उपलब्ध है, जिसके विकल्प का उपयोग हम इस बात के आधार पर कर सकते हैं कि हमें फ़ंक्शन से किस आउटपुट की आवश्यकता है। आप फ़ंक्शन के एक ही संस्करण को चुनने पर बहस करने की तुलना में अपवाद को फेंकने के लिए फ़ंक्शन लिखने और फ़ंक्शन आवरण को बनाए रखने में कम समय व्यतीत करेंगे।


3
+1 क्योंकि मुझे हमेशा पसंद का विचार पसंद है और क्योंकि इस पैटर्न में प्रोग्रामर को अपने स्वयं के इनपुट को मान्य करने के लिए प्रोत्साहित करने की प्रवृत्ति है। एक TryFoo फ़ंक्शन का मात्र अस्तित्व यह स्पष्ट करता है कि कुछ इनपुट संयोजन समस्याएँ पैदा कर सकते हैं और यदि दस्तावेज़ीकरण यह बताता है कि वे संभावित समस्याएं क्या हैं, तो कोडर उनके लिए जाँच कर सकता है और एक स्वच्छ फैशन में अमान्य इनपुट को संभाल सकता है, बस एक अपवाद को पकड़कर। या एक खाली सेट का जवाब। या वे आलसी हो सकते हैं। किसी भी तरह, निर्णय उनका है।
aleppke

19
नहीं, एक खाली सेट गणितीय रूप से सही उत्तर है। कुछ और करने से गणित पर दृढ़ता से सहमति बनती है, जिसे कतई नहीं किया जाना चाहिए। जब हम इस पर होते हैं, तो क्या हम घातांक फ़ंक्शन को फिर से परिभाषित करने के लिए एक त्रुटि को फेंक देंगे यदि घातांक शून्य के बराबर है, क्योंकि हम तय करते हैं कि हम उस सम्मेलन को पसंद नहीं करते हैं जो "शून्य" शक्ति के लिए उठाया गया कोई भी संख्या 1 के बराबर है?
वाइल्डकार्ड

1
मैं कुछ इसी तरह का जवाब देने वाला था। Linq विस्तार के तरीकों Single()और SingleOrDefault()तुरंत मन में उछला। एकल शून्य या> 1 परिणाम होने पर एक अपवाद को फेंक देता है, जबकि SingleOrDefault फेंक नहीं देगा, और बदले में default(T)। शायद ओपी इस्तेमाल कर सकता है CombinationsOf()और CombinationsOfOrThrow()
रबरडुक

1
@Wildcard - आप एक ही इनपुट के लिए दो अलग-अलग परिणामों के बारे में बात कर रहे हैं जो एक ही बात नहीं है। ओपी केवल एक परिणाम को चुनने में दिलचस्पी रखता है या बी) एक अपवाद को फेंकना जो एक परिणाम नहीं है।
जेम्स स्नेल

4
Singleऔर SingleOrDefault(या Firstऔर FirstOrDefault) एक पूरी तरह से अलग कहानी है, @RubberDuck हैं। मेरी पिछली टिप्पणी से मेरा उदाहरण उठा। यह पूरी तरह से ठीक नहीं है कि क्वेरी के लिए "दो से अधिक क्या मौजूद है?" , क्योंकि यह एक गणितीय ध्वनि और समझदार उत्तर है। वैसे भी, अगर आप पूछ रहे हैं कि "पहले से दो से बड़ा अभाज्य क्या है?" कोई प्राकृतिक उत्तर नहीं है। आप सिर्फ सवाल का जवाब नहीं दे सकते, क्योंकि आप एक ही नंबर के लिए पूछ रहे हैं। यह कोई नहीं है (यह एक एकल संख्या नहीं है, लेकिन एक सेट है), 0. नहीं। इसलिए हम एक अपवाद फेंकते हैं।
पॉल केर्टशर 11

4

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

इस प्रकार मैं ArgumentException के लिए मतदान करूँगा ताकि उपयोगकर्ता को यह समझने के लिए आवश्यक जानकारी प्रदान की जा सके कि क्या गलत हुआ।

एक उदाहरण के रूप public static TSource ElementAt<TSource>(this IEnumerable<TSource>, Int32)में, लिनक में फ़ंक्शन की जांच करें । यदि स्रोत में तत्वों की संख्या से 0 या अधिक से कम या अधिक है तो एक ArgumentOutOfRangeException को फेंकता है। इस प्रकार अनुक्रमणिका को कॉल करने वाले द्वारा प्रदत्त गणना के संबंध में मान्य किया जाता है।


3
भाषा की एक समान स्थिति का उदाहरण देने के लिए +1।
जेम्स स्नेल

13
अजीब तरह से, आपके उदाहरण ने मुझे सोच लिया, और मुझे कुछ ऐसा करने के लिए प्रेरित किया जो मुझे लगता है कि एक मजबूत प्रति-उदाहरण है। जैसा कि मैंने उल्लेख किया है, इस विधि को LINQ- जैसा बनाया गया है, ताकि उपयोगकर्ता इसे अन्य LINQ विधियों के साथ जोड़ सकें। यदि आप new[] { 1, 2, 3 }.Skip(4).ToList();एक खाली सेट प्राप्त करते हैं, जो मुझे लगता है कि खाली सेट लौटना शायद यहाँ बेहतर विकल्प है।
anaximander

14
यह एक भाषा शब्दार्थ समस्या नहीं है, समस्या डोमेन के शब्दार्थ पहले से ही सही उत्तर प्रदान करते हैं, अर्थात खाली सेट को वापस करना है। कुछ और करने से कम्बिनेटरिक समस्या डोमेन में काम करने वाले किसी व्यक्ति के लिए कम से कम विस्मय के सिद्धांत का उल्लंघन होता है।
उकको

1
मैं खाली सेट लौटाने के तर्कों को समझने लगा हूं। यह समझ में क्यों आएगा। कम से कम इस विशेष उदाहरण के लिए।
साकेकर

2
@ स्केकर, बिंदु को घर लाने के लिए: यदि प्रश्न " कितने संयोजन हैं ..." तो "शून्य" पूरी तरह से मान्य उत्तर होगा। इसी तरह, "क्या कर रहे हैं एक पूरी तरह से वैध जवाब के रूप में खाली सेट है संयोजन ऐसा है कि ..."। यदि प्रश्न था, " पहला संयोजन ऐसा क्या है ...", तब और केवल तभी एक अपवाद उपयुक्त होगा, क्योंकि प्रश्न उत्तर योग्य नहीं है। पॉल के की टिप्पणी भी देखें ।
वाइल्डकार्ड

3

आपको निम्न में से एक करना चाहिए (हालांकि संयोजन की नकारात्मक संख्या जैसी बुनियादी समस्याओं पर लगातार फेंकना जारी है):

  1. दो कार्यान्वयन प्रदान करें, एक वह जो एक खाली सेट लौटाता है जब एक साथ इनपुट निरर्थक होते हैं, और एक जो फेंकता है। उन्हें कॉल करने का प्रयास करें CombinationsOfऔर CombinationsOfWithInputCheck। या आपको जो अच्छा लगे। आप इसे उलट सकते हैं इसलिए इनपुट-जाँच एक छोटा नाम है और सूची एक है CombinationsOfAllowInconsistentParameters

  2. Linq विधियों के लिए, IEnumerableआपके द्वारा उल्लिखित सटीक आधार पर खाली लौटें । फिर, अपने पुस्तकालय में इन Linq तरीकों को जोड़ें:

    public static class EnumerableExtensions {
       public static IEnumerable<T> ThrowIfEmpty<T>(this IEnumerable<T> input) {
          return input.IfEmpty<T>(() => {
             throw new InvalidOperationException("An enumerable was unexpectedly empty");
          });
       }
    
       public static IEnumerable<T> IfEmpty<T>(
          this IEnumerable<T> input,
          Action callbackIfEmpty
       ) {
          var enumerator = input.GetEnumerator();
          if (!enumerator.MoveNext()) {
             // Safe because if this throws, we'll never run the return statement below
             callbackIfEmpty();
          }
          return EnumeratePrimedEnumerator(enumerator);
       }
    
       private static IEnumerable<T> EnumeratePrimedEnumerator<T>(
          IEnumerator<T> primedEnumerator
       ) {
          yield return primedEnumerator.Current;
          while (primedEnumerator.MoveNext()) {
             yield return primedEnumerator.Current;
          }
       }
    }
    

    अंत में, उस तरह का उपयोग करें:

    var result = someInputSet
       .CombinationsOf(4, CombinationsGenerationMode.Distinct)
       .ThrowIfEmpty()
       .Select(combo => /* do some operation to a combination */)
       .ToList();
    

    या इस तरह:

    var result = someInputSet
       .CombinationsOf(4, CombinationsGenerationMode.Distinct)
       .IfEmpty(() => _log.Warning(
          $@"Unexpectedly received no results when creating combinations for {
             nameof(someInputSet)}"
       ))
       .Select(combo => /* do some operation to a combination */)
       .ToList();
    

    कृपया ध्यान दें कि सार्वजनिक विधि से भिन्न होने की निजी विधि को फेंकने या कार्रवाई के व्यवहार के लिए आवश्यक है जब लाइनक चेन कुछ समय बाद के बजाय जब इसे एनुमरेट किया जाता है। आप चाहते हैं कि यह तुरंत फेंक दिया जाए।

    ध्यान दें, हालांकि, निश्चित रूप से यह निर्धारित करने के लिए कम से कम पहले आइटम की गणना करनी है कि क्या कोई आइटम हैं। यह एक संभावित वापसी मुझे लगता है कि ज्यादातर तथ्य भविष्य के किसी भी दर्शकों को काफी आसानी से कारण कर सकते हैं कि एक है कि से कम है है ThrowIfEmptyविधि है कम से कम एक आइटम की गणना करने में है, तो चाहिए नहीं यह ऐसा करके आश्चर्यचकित हो। लेकिन आप कभी नहीं जान पाते। आप इसे और अधिक स्पष्ट कर सकते हैं ThrowIfEmptyByEnumeratingAndReEmittingFirstItem। लेकिन यह विशाल overkill की तरह लगता है।

मुझे लगता है कि # 2 काफी, अच्छी तरह से, बहुत बढ़िया है! अब बिजली कॉलिंग कोड में है, और कोड का अगला पाठक ठीक से समझ जाएगा कि यह क्या कर रहा है, और अप्रत्याशित अपवादों से निपटना नहीं होगा।


कृपया इसका मतलब बताएं। मेरे पोस्ट में "सेट की तरह बर्ताव नहीं" और कुछ ऐसा क्यों है?
एरिक

आप मूल रूप से मेरे उत्तर के समान हैं, क्वेरी को लपेटने के बजाए यदि आप एक
if condition

मैं नहीं देख सकता कि मेरा उत्तर "मूल रूप से आपके उत्तर के समान है"। वे मुझे पूरी तरह से अलग लगते हैं।
एरिक

मूल रूप से आप "मेरी बुरी कक्षा" की एक ही स्थिति लागू कर रहे हैं। लेकिन आप यह नहीं बता रहे हैं कि ^ ^ क्या आप सहमत हैं, कि क्या आप क्वेरी परिणाम में 1 तत्व के अस्तित्व को लागू कर रहे हैं?
GameDeveloper

आप स्पष्ट रूप से बेवकूफ प्रोग्रामर के लिए और अधिक स्पष्ट रूप से बोलने जा रहे हैं जो अभी भी नहीं मिल रहे हैं जो आप के बारे में बात कर रहे हैं। क्या वर्ग खराब है? यह बुरा क्यों है? मैं कुछ भी लागू नहीं कर रहा हूँ। मैं वर्ग के USER को वर्ग के निर्माता के बजाय अंतिम व्यवहार तय करने की अनुमति दे रहा हूं। यह एक सुसंगत कोडिंग प्रतिमान का उपयोग करने की अनुमति देता है जहां लाइनक विधियां एक कम्प्यूटेशनल पहलू के कारण बेतरतीब ढंग से नहीं फेंकती हैं जो वास्तव में सामान्य नियमों का उल्लंघन नहीं है जैसे कि आपने एक बार में 1 आइटम मांगा था।
एरिक

2

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

मुझे लगता है कि यह कॉल करने वाले की अपेक्षाओं पर निर्भर करता है यदि यह कोई त्रुटि है, या एक स्वीकार्य परिणाम है - तो मैं कॉल करने वाले को विकल्प स्थानांतरित कर दूंगा। शायद एक विकल्प का परिचय दें?

.CombinationsOf(4, CombinationsGenerationMode.Distinct, Options.AllowEmptySets)


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

यदि कॉलर एक ऐसे सेट की अपेक्षा करता है जो खाली नहीं है, तो यह कॉलर पर निर्भर है कि वह एक खाली सेट को हैंडल करे या अपवाद को फेंक दे। जहां तक ​​कैली का सवाल है, एक खाली सेट एक बिल्कुल ठीक जवाब है। और आपके पास एक से अधिक कॉलर हो सकते हैं, अलग-अलग राय के साथ कि क्या खाली सेट ठीक हैं या नहीं।
gnasher729

2

यदि कोई स्पष्ट उत्तर नहीं है, तो निर्णय लेने के दो तरीके हैं:

  • पहले एक विकल्प मानकर कोड लिखें, फिर दूसरा। विचार करें कि कौन सा व्यवहार में सबसे अच्छा काम करेगा।

  • यह इंगित करने के लिए "सख्त" बूलियन पैरामीटर जोड़ें कि आप मापदंडों को कड़ाई से सत्यापित करना चाहते हैं या नहीं। उदाहरण के लिए, जावा के SimpleDateFormatपास setLenientइनपुट इनपुट का प्रयास करने का एक तरीका है जो प्रारूप से पूरी तरह मेल नहीं खाता है। बेशक, आपको तय करना होगा कि डिफ़ॉल्ट क्या है।


2

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

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

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

इससे पहले किए गए 12 से अधिक अंकों के बारे में कुछ भी समझ में नहीं आता है और पहले के 12 उत्तरों में समझाया गया है
gnat

1

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

  • यदि आप Infएक पायथन लाइब्रेरी में लौटते हैं , तो लोग आपको त्रुटियों को छिपाने के लिए हमला करेंगे
  • यदि आप एक मैटलैब लाइब्रेरी में कोई त्रुटि उठाते हैं, तो लोग आपको लापता मानों के साथ डेटा संसाधित करने में विफल होने के लिए हमला करेंगे

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

समाधान जो उपयोगकर्ता को चुनने देते हैं (जैसे "सख्त" पैरामीटर जोड़ना) निश्चित नहीं हैं, क्योंकि वे मूल प्रश्न को एक नए समकक्ष के साथ प्रतिस्थापित करते हैं: "कौन सा मान strictडिफ़ॉल्ट होना चाहिए?"


2
मैंने अपने उत्तर में NaN तर्क का उपयोग करने के बारे में सोचा और मैं आपकी राय साझा करता हूं। हम ओपी के
गेम

0

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

सामान्य सेट नियम:

  • Set.Foreach (विधेय); // हमेशा खाली सेट के लिए सच है
  • Set.Exists (विधेय); // हमेशा खाली सेट के लिए झूठे रिटर्न

आपका प्रश्न बहुत ही सूक्ष्म है:

  • यह हो सकता है कि आपके फ़ंक्शन के इनपुट को एक अनुबंध का सम्मान करना है : उस मामले में किसी भी अमान्य इनपुट को एक अपवाद उठाना चाहिए, यही है, फ़ंक्शन नियमित मापदंडों के तहत काम नहीं कर रहा है।

  • यह हो सकता है कि आपके फ़ंक्शन के इनपुट को एक सेट की तरह व्यवहार करना है , और इसलिए एक खाली सेट को वापस करने में सक्षम होना चाहिए।

अब अगर मैं तुम में होता तो मैं "सेट" तरीके से जाता, लेकिन एक बड़े "ब्यूट" के साथ।

मान लें कि आपके पास एक संग्रह है कि "हाइपोटिस द्वारा" केवल महिला छात्रों को होना चाहिए:

class FemaleClass{

    FemaleStudent GetAnyFemale(){
        var femaleSet= mySet.Select( x=> x.IsFemale());
        if(femaleSet.IsEmpty())
            throw new Exception("No female students");
        else
            return femaleSet.Any();
    }
}

अब आपका संग्रह "शुद्ध सेट" नहीं है, क्योंकि आपके पास इस पर एक अनुबंध है, और इसलिए आपको एक अपवाद के साथ अपना अनुबंध लागू करना चाहिए।

जब आप अपने "सेट" कार्यों का उपयोग शुद्ध तरीके से करते हैं तो आपको खाली सेट के मामले में अपवादों को नहीं फेंकना चाहिए, लेकिन अगर आपके पास ऐसे संग्रह हैं जो अधिक "शुद्ध सेट" नहीं हैं, तो आपको उन अपवादों को फेंक देना चाहिए जहां उचित है

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

आपके मामले में ऐसा करना एक अच्छा विचार है:

List SomeMethod( Set someInputSet){
    var result = someInputSet
        .CombinationsOf(4, CombinationsGenerationMode.Distinct)
        .Select(combo => /* do some operation to a combination */)
        .ToList();

    // the only information here is that set is empty => there are no combinations

    // BEWARE! if 0 here it may be invalid input, but also a empty set
    if(result.Count == 0)  //Add: "&&someInputSet.NotEmpty()"

    // we go a step further, our API require combinations, so
    // this method cannot satisfy the API request, then we throw.
         throw new Exception("you requsted impossible combinations");

    return result;
}

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

नई जटिलता को जोड़ने के लिए, केवल यह दिखाने के लिए कि आप लिख सकते हैं linq questions विधियां आपकी समस्या के लिए उपयुक्त नहीं हैं , मुझे पूरा यकीन है कि अगर ओपी हमें इसके बारे में अधिक बता सकता है कि यह डोमेन है, तो शायद हम उस स्थान को पा सकते हैं जहां अपवाद वास्तव में आवश्यक है (यदि सब पर, यह संभव है कि समस्या को किसी भी अपवाद की आवश्यकता नहीं है)।


समस्या यह है कि आप किसी समस्या को हल करने के लिए गणितीय रूप से परिभाषित वस्तुओं का उपयोग कर रहे हैं, लेकिन समस्या को स्वयं एक गणितीय रूप से परिभाषित वस्तु की आवश्यकता नहीं हो सकती है, उत्तर के रूप में (यहाँ एक सूची लौटाते हुए)। यह सब समस्या के उच्च-स्तर पर निर्भर करता है, चाहे आप इसे कैसे भी हल करें, इसे एन्कैप्सुलेशन / सूचना छिपाना कहा जाता है।
गेमडेवलर

जिस कारण से आपके "SomeMethod" को अब सेट की तरह व्यवहार नहीं करना चाहिए, वह यह है कि आप "सेट से बाहर" जानकारी का एक टुकड़ा पूछ रहे हैं, विशेष रूप से टिप्पणी किए गए भाग को देखें और & quot; someInputSet.NotEmpty (TM)
GameDeveloper

1
नहीं! आपको अपनी महिला वर्ग में अपवाद नहीं फेंकना चाहिए। आपको बिल्डर पैटर्न का उपयोग करना चाहिए जो FemaleClassयह बताता है कि आप तब तक एक उदाहरण प्राप्त नहीं कर सकते जब तक कि इसमें केवल महिलाएं न हों (यह सार्वजनिक रूप से रचनात्मक नहीं है, केवल बिल्डर वर्ग एक उदाहरण को सौंप सकता है), और संभवतः इसमें कम से कम एक महिला हो । फिर FemaleClassएक तर्क के रूप में जगह लेने वाले आपके कोड को अपवादों को संभालने की आवश्यकता नहीं है क्योंकि ऑब्जेक्ट गलत स्थिति में है।
1

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

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