क्या विधि के तर्क के रूप में बूलियन अस्वीकार्य हैं? [बन्द है]


123

मेरा एक सहयोगी बताता है कि विधि तर्क के रूप में बूलियन स्वीकार्य नहीं हैं । उन्हें गणनाओं द्वारा प्रतिस्थापित किया जाएगा। पहले तो मुझे कोई फायदा नहीं हुआ, लेकिन उन्होंने मुझे एक उदाहरण दिया।

समझने में आसान क्या है?

file.writeData( data, true );

या

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

अब मैं समझ गया! ;-)
यह निश्चित रूप से एक उदाहरण है जहां एक पैरामीटर दूसरे पैरामीटर के रूप में कोड को अधिक पठनीय बनाता है।

तो, इस विषय पर आपकी क्या राय है?


7
यह एक बहुत ही दिलचस्प पढ़ा गया था, मैं इस पद्धति को अधिक बार लागू करूंगा।
सारा Chipps

hrm, ive ने पहले ऐसा किया था, लेकिन कभी भी यह महसूस नहीं किया कि यह एक डिज़ाइन पैटर्न कितना अच्छा है। तो एनम फ़ाइल में जाता है?
शॉन

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

2
अगर यह अस्वीकार्य है तो एडवेंचर टाइम पर सिर्फ नींबू वाले से पूछें
ajax333221

जवाबों:


131

बूलियन "हाँ / नहीं" विकल्पों का प्रतिनिधित्व करता है। यदि आप "हां / नहीं" का प्रतिनिधित्व करना चाहते हैं, तो एक बूलियन का उपयोग करें, यह आत्म-व्याख्यात्मक होना चाहिए।

लेकिन अगर यह दो विकल्पों में से एक विकल्प है, जिसमें से कोई भी स्पष्ट रूप से हां या नहीं है, तो एक एनम कभी-कभी अधिक पठनीय हो सकती है।


3
इसके अलावा, विधि नाम के बारे में स्पष्ट होना चाहिए कि तर्क हाँ या नहीं क्या करता है अर्थात शून्य टर्नलाइटऑन (बूल) क्लीली रूप से सही या हाँ सेट करने पर प्रकाश को ट्यून करेगा।
सिमोन

10
हालांकि इस मामले में मैं शायद स्थिति के आधार पर टर्नलाइटऑन () और टर्नलाइटऑफ () हो सकता हूं।
स्केफमैन

14
"टर्नलाइटऑन (झूठा)" का अर्थ है "प्रकाश को चालू न करें"? Confusiong।
जय बज़ुजी

17
कैसे के बारे में setLightOn(bool)
Finbarr

10
देर से टिप्पणी, लेकिन @ जय बज़ुजी: यदि आपकी विधि को टर्नलाइट कहा जाता है, और आप झूठे में गुजरते हैं, तो आप विधि को बिल्कुल भी नहीं कह सकते हैं, झूठे में पास होने पर प्रकाश को चालू नहीं करना कहते हैं। यदि प्रकाश पहले से ही है, तो इसका मतलब यह नहीं है कि इसे बंद कर दें, इसका मतलब यह है कि इसे चालू न करें ... यदि आपके पास 'ऑन' और 'ऑफ' के साथ एक एनाम है, तो टर्नलाइट ( ऑन), टर्नलाइट (ऑफ)। मैं स्केफ़मैन थो के साथ सहमत हूं, मैं दो अलग-अलग स्पष्ट तरीकों, टर्नलाइटऑन () और टर्नलाइटऑफ़ () में शामिल होना चाहता हूं। (BTW: यह सामान अंकल बोब्स की किताब "क्लीन कोड" में बताया गया है)
फिल


32

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

lock.setIsLocked(True);

या

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

इस मामले में, मैं बूलियन विकल्प चुन सकता हूं क्योंकि मुझे लगता है कि यह काफी स्पष्ट और स्पष्ट है, और मुझे पूरा यकीन है कि मेरे लॉक में दो से अधिक राज्य नहीं होंगे। फिर भी, दूसरी पसंद वैध है, लेकिन अनावश्यक रूप से जटिल, IMHO।


2
आपके उदाहरण में मेरे पास दो विधियाँ होंगी। lock.lock () lock.release () और lock.IsSet, लेकिन यह सब उपभोग कोड के लिए सबसे अधिक समझ में आता है।
रॉबर्ट पॉलसन

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

मैं पूरी तरह से सहमत हूं :), मैं अभी तक विशेष रूप से स्यूडोकोड की पेशकश पर टिप्पणी कर रहा था। मैं आपके उत्तर से सहमत हूं।
रॉबर्ट पॉलसन

14

मेरे लिए, न तो बूलियन का उपयोग करना और न ही गणना एक अच्छा तरीका है। रॉबर्ट सी। मार्टिन ने अपने क्लीन कोड टिप # 12 में इसे बहुत स्पष्ट रूप से कैप्चर किया : बूलियन आर्गुमेंट्स को हटा दें :

बूलियन तर्क जोर से घोषणा करते हैं कि फ़ंक्शन एक से अधिक कार्य करता है। वे भ्रमित कर रहे हैं और इसे समाप्त किया जाना चाहिए।

यदि कोई विधि एक से अधिक कार्य करती है, तो आपको दो अलग-अलग विधियाँ लिखनी चाहिए, उदाहरण के लिए आपके मामले में: file.append(data)और file.overwrite(data)

एक गणना का उपयोग चीजों को स्पष्ट नहीं करता है। यह कुछ भी नहीं बदलता है, यह अभी भी एक झंडा तर्क है।


7
क्या इसका मतलब यह नहीं है कि एक ऐसा फ़ंक्शन जो ASCII स्ट्रिंग की लंबाई N को स्वीकार करता है वह 128 ^ N चीजें करता है?
det

@delty क्या यह गंभीर टिप्पणी है? यदि हाँ, तो क्या आप एक स्ट्रिंग के सभी संभावित मूल्यों पर अक्सर कोड करते हैं? क्या बूलियन तर्क के मामले के साथ कोई संभावित तुलना है?
पास्कल थिवेंट

मेरा मानना ​​है कि जब आप किसी ऑब्जेक्ट के अंदर बूलियन मान सेट कर रहे हैं तो वे स्वीकार्य हैं। एक आदर्श उदाहरण होगा setVisible(boolean visible) { mVisible = visible; }। आपके द्वारा सुझाया गया विकल्प क्या होगा?
ब्रैड

2
@ ब्रैड शो () {mVanish = true} छिपाएँ () {mV अदृश्य = झूठा}
ओसवाल्डो अकुआन

@ ओस्वाल्डो, जबकि अभी भी सही है, मुझे नहीं लगता कि विभिन्न मूल्यों के लिए बूलियन को असाइन करने के लिए दो अलग-अलग तरीकों का कुल अर्थ है। आपके पास setIntToOne (), setIntToTwo () setIntToThree () सही नहीं है? यह थोड़ा अधिक अस्पष्ट है जब आपके पास केवल दो संभावित मूल्य हो सकते हैं लेकिन स्वच्छता के लिए उस मामले में एक बूलियन का उपयोग करें।
ब्रैड

13

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


13

क्यूबाइल मिसाइल संकट के दौरान संयुक्त राष्ट्र में राजदूत ज़ोरिन को दिया गया सवाल अडलई स्टीवेंसन याद है ?

"आप अभी विश्व राय के कठघरे में हैं, और आप हां या ना में जवाब दे सकते हैं । आपने इनकार किया है कि [मिसाइलें] मौजूद हैं, और मैं जानना चाहता हूं कि क्या मैं आपको सही तरीके से समझ पाया हूं .... मैं इंतजार करने के लिए तैयार हूं।" मेरे जवाब के लिए जब तक नर्क खत्म नहीं हो जाता, अगर यह आपका फैसला है। ”

यदि आपके पास जो झंडा है, वह आपके स्वभाव का है, तो आप इसे बाइनरी निर्णय पर पिन कर सकते हैं , और यह निर्णय कभी भी तीन-तरफ़ा या n-तरह के निर्णय में नहीं बदलेगा, बूलियन के लिए जाना होगा। संकेत: आपके ध्वज को XXX कहा जाता है ।

एक मोड स्विच है कि कुछ के मामले में यह बूलियन मत करो । जब आप पहली बार में विधि लिखते हैं तो आपके विचार से हमेशा एक और विधा होती है।

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


13

इसके खराब होने के दो कारण हैं:

  1. क्योंकि कुछ लोग तरीके लिखेंगे:

    ProcessBatch(true, false, false, true, false, false, true);
    

    यह स्पष्ट रूप से बुरा है क्योंकि मापदंडों को मिलाना बहुत आसान है, और आपको यह देखकर कोई विचार नहीं है कि आप क्या निर्दिष्ट कर रहे हैं। बस एक बूल हालांकि बहुत बुरा नहीं है।

  2. क्योंकि एक साधारण हाँ / नहीं शाखा द्वारा प्रोग्राम प्रवाह को नियंत्रित करने का मतलब हो सकता है कि आपके पास दो पूरी तरह से अलग-अलग कार्य हैं जो एक अजीब तरीके से एक में लिपटे हुए हैं। उदाहरण के लिए:

    public void Write(bool toOptical);
    

    वास्तव में, यह दो तरीके होने चाहिए

    public void WriteOptical();
    public void WriteMagnetic();
    

    क्योंकि इनमें कोड पूरी तरह से अलग हो सकता है; उन्हें अलग-अलग त्रुटि हैंडलिंग और सत्यापन के सभी प्रकार करने पड़ सकते हैं, या शायद आउटगोइंग डेटा को अलग-अलग प्रारूपित करना होगा। आप यह नहीं बता सकते हैं कि केवल उपयोग करके Write()या यहां तक ​​कि Write(Enum.Optical)(बेशक आप उन तरीकों में से किसी को भी बस आंतरिक तरीकों को कॉल कर सकते हैं WriteOptical / Mag यदि आप चाहते हैं)।

मुझे लगता है कि यह सिर्फ निर्भर करता है। मैं # 1 को छोड़कर इसके बारे में बहुत बड़ा सौदा नहीं करूंगा।


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

यह जवाब कुछ सुधार से लाभ हो सकता है, हालांकि! ;-)
यरिक

7

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


बस विधि को बहुत वर्णनात्मक बनाएं ताकि यह स्पष्ट हो कि क्या सही है या हाँ का अर्थ है।
सिमोन

6

बूलियन उन भाषाओं में ठीक हो सकते हैं, जिनके नाम पैरामीटर हैं, जैसे पायथन और ऑब्जेक्टिव-सी, क्योंकि नाम समझा सकता है कि पैरामीटर क्या हैं:

file.writeData(data, overwrite=true)

या:

[file writeData:data overwrite:YES]

1
IMHO, writeData () एक बूलियन पैरामीटर का उपयोग करने का एक बुरा उदाहरण है, भले ही नामित पैरामीटर हैं या समर्थित नहीं हैं। कोई फर्क नहीं पड़ता कि आप पैरामीटर का नाम कैसे देते हैं, गलत मूल्य का अर्थ स्पष्ट नहीं है!
यारिक

4

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

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

dim append as boolean = true
file.writeData( data, append );

या मैं और अधिक सामान्य पसंद करते हैं

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

दूसरा: आपके द्वारा दिया गया Enum उदाहरण केवल "बेहतर" है क्योंकि आप एक CONST से गुजर रहे हैं। अधिकांश अनुप्रयोगों में कम से कम कुछ होने की संभावना सबसे अधिक है अगर अधिकांश समय पैरामीटर जो फ़ंक्शन के लिए पारित किए जाते हैं, तो VARIABLES हैं। जिस स्थिति में मेरा दूसरा उदाहरण (अच्छे नामों के साथ चर देना) ज्यादा बेहतर है और एनम ने आपको बहुत कम लाभ दिया होगा।


1
हालांकि मैं मानता हूं कि इस राइटडैटा () उदाहरण के मामले में, कई मामलों में बूलियन पैरामीटर स्वीकार्य हैं, इसलिए बेंडियन पैरामीटर जैसे किAppAppend बहुत अनुचित है। कारण सरल है: यह तुरंत स्पष्ट नहीं है कि गलत का अर्थ क्या है।
यारिक

4

Enums का एक निश्चित लाभ है, लेकिन आपको केवल अपने सभी बूलियनों की जगह enums से नहीं जाना चाहिए। ऐसे कई स्थान हैं जहाँ सही / गलत वास्तव में प्रस्तुत करने का सबसे अच्छा तरीका है।

हालाँकि, उन्हें विधि तर्कों के रूप में उपयोग करना थोड़ा संदेहास्पद है, बस इसलिए कि आप उन चीजों को खोदे बिना नहीं देख सकते हैं जो वे करने वाले हैं, क्योंकि वे आपको देखते हैं कि वास्तव में क्या है / गलत

गुण (विशेष रूप से C # 3 ऑब्जेक्ट इनिशियलाइज़र के साथ) या कीवर्ड तर्क (एक ला रूबी या अजगर) एक बेहतर तरीका है जहाँ आप अन्यथा एक बूलियन तर्क का उपयोग करेंगे।

C # उदाहरण:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

माणिक उदाहरण

validates_presence_of :name, :allow_nil => true

पायथन उदाहरण

connect_to_database( persistent=true )

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


4

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

यह नियम केवल शैली का प्रश्न है, बग या रनटाइम प्रदर्शन के लिए क्षमता का नहीं। एक बेहतर नियम यह होगा कि "पठनीयता के कारणों के लिए बूलियंस को दुश्मनी पसंद करें"।

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

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

उदाहरण के लिए, यदि आपकी कक्षा में गुण हैं

public bool IsFoo
public bool IsBar

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

enum FooBarType { IsFoo, IsBar, IsNeither };

4

आपके सहकर्मी के लिए कुछ नियम बेहतर हो सकते हैं:

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

3

एक बूलियन केवल तभी स्वीकार्य होगा जब आप फ्रेमवर्क की कार्यक्षमता का विस्तार करने का इरादा नहीं रखते हैं। एनम को पसंद किया जाता है क्योंकि आप एनम का विस्तार कर सकते हैं और फ़ंक्शन कॉल के पिछले कार्यान्वयन को नहीं तोड़ सकते हैं।

एनम का अन्य लाभ यह है कि पढ़ना आसान है।


2

यदि विधि एक प्रश्न पूछती है जैसे:

KeepWritingData (DataAvailable());

कहाँ पे

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

बूलियन विधि तर्क बिल्कुल सही समझ में आता है।


किसी दिन आपको "यदि आपके पास खाली जगह है, तो लिखते रहें" जोड़ने की आवश्यकता होगी, और फिर आप किसी भी तरह बूल से एनम तक जाएंगे।
इल्या रायजेनकोव

और फिर आपके पास ब्रेकिंग परिवर्तन होगा, या अप्रचलित अधिभार होगा, या हो सकता है कि केप्पवर्टिंगडैटेएक्स जैसे कुछ हो :) :)
इल्या

1
@ इलिया या शायद आप नहीं करेंगे! एक संभावित स्थिति बनाना जहां कोई भी वर्तमान में मौजूद नहीं है, समाधान की उपेक्षा नहीं करता है।
जेसी सी। स्लीपर

1
जेसी का अधिकार। परिवर्तन की योजना बनाना मूर्खतापूर्ण है। जो करता है वह समझ में आता है। इस मामले में, बूलियन सहज और स्पष्ट दोनों है। c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html
डेरेक पार्क

@ डेरेक, इस मामले में, बूलियन की भी आवश्यकता नहीं है, क्योंकि डेटावेल हमेशा सच हो जाता है :)
इल्या

2

यह विधि पर निर्भर करता है। यदि विधि कुछ ऐसा करती है जो स्पष्ट रूप से एक सच्ची / झूठी बात है, तो यह ठीक है, जैसे नीचे [हालांकि मैं यह नहीं कह रहा हूं कि यह इस पद्धति के लिए सबसे अच्छा डिज़ाइन है, यह सिर्फ एक उदाहरण है जहां उपयोग स्पष्ट है]।

CommentService.SetApprovalStatus(commentId, false);

हालांकि ज्यादातर मामलों में, जैसे कि आप जिस उदाहरण का उल्लेख करते हैं, एक गणना का उपयोग करना बेहतर है। .NET फ्रेमवर्क में ही कई उदाहरण हैं जहां इस सम्मेलन का पालन नहीं किया गया है, लेकिन ऐसा इसलिए है क्योंकि उन्होंने इस डिजाइन दिशानिर्देश को चक्र पर काफी देर से पेश किया।


2

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


1
तीसरे संभावित विकल्प के रूप में प्रस्तुत करने के बारे में क्या? ;-))
यारिक

2

Enums निश्चित रूप से कोड को अधिक पठनीय बना सकते हैं। (.Net कम से कम) के लिए बाहर देखने के लिए अभी भी कुछ चीजें हैं

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

यदि आपके एनम आपके कोड के लिए निजी हैं (कभी सार्वजनिक रूप से उजागर नहीं किए जाते हैं) तो आप यहां पढ़ना बंद कर सकते हैं।

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

मैं कानूनी तौर पर लिख सकता हूं

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

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

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

इसका केवल Enum.IsDefinedयह है कि यह प्रतिबिंब का उपयोग करता है और धीमा है। यह भी एक संस्करण समस्या ग्रस्त है। यदि आपको अक्सर एनम मान की जांच करने की आवश्यकता है, तो आप निम्नलिखित से बेहतर होंगे:

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

वर्जनिंग समस्या यह है कि पुराना कोड केवल यह जान सकता है कि आपके पास मौजूद 2 एनम को कैसे हैंडल करना है। यदि आप एक तीसरा मान जोड़ते हैं, तो Enum.IsDefined सत्य होगा, लेकिन पुराना कोड आवश्यक रूप से इसे संभाल नहीं सकता है। ओह।

और भी मज़ेदार है जो आप [Flags]enums के साथ कर सकते हैं , और इसके लिए सत्यापन कोड थोड़ा अलग है।

मैं यह भी ध्यान रखें चल जाएगा कि पोर्टेबिलिटी के लिए, आप कॉल का उपयोग करना चाहिए ToString()enum पर, और उपयोग Enum.Parse()करते समय उन्हें वापस पढ़ने। दोनों ToString()और Enum.Parse()संभाल कर सकते हैं [Flags]enum के रूप में अच्छी तरह से है, इसलिए उन्हें इस्तेमाल करने के लिए नहीं कोई कारण नहीं है। ध्यान रखें, यह अभी तक एक और नुकसान है, क्योंकि अब आप संभवतः कोड तोड़ने के बिना एनम का नाम भी नहीं बदल सकते हैं।

तो, कभी-कभी आपको उपरोक्त सभी को तौलना पड़ता है जब आप खुद से पूछते हैं कि क्या मैं सिर्फ एक बूल के साथ दूर हो सकता हूं?


1

IMHO ऐसा लगता है जैसे किसी भी स्थिति के लिए एक स्पष्ट विकल्प होगा जहां दो से अधिक विकल्प संभव हैं। लेकिन निश्चित रूप से ऐसी परिस्थितियां हैं जहां एक बूलियन आप सभी की जरूरत है। उस मामले में मैं कहूंगा कि एक एनम का उपयोग करना जहां एक बूल काम करेगा, 7 शब्दों का उपयोग करने का एक उदाहरण होगा जब 4 करेगा।


0

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

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


0

कभी-कभी यह ओवरलोड के साथ अलग-अलग व्यवहार को मॉडल करने के लिए बस सरल होता है। अपने उदाहरण से जारी रखने के लिए होगा:

file.appendData( data );  
file.overwriteData( data );

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

Enums कर सकते हैं, कुछ मामलों में कोड को अधिक पठनीय बनाते हैं, हालांकि कुछ भाषाओं में सटीक एनम मान को मान्य करना (उदाहरण के लिए C) मुश्किल हो सकता है।

अक्सर एक बूलियन पैरामीटर को नए अधिभार के रूप में मापदंडों की सूची में जोड़ा जाता है। .NET में एक उदाहरण है:

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

बाद का अधिभार पहले की तुलना में .NET फ्रेमवर्क के बाद के संस्करण में उपलब्ध हो गया।

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


संपादित करें

C # के नए संस्करणों में नामांकित तर्कों का उपयोग करना संभव है जो, IMO, कॉलिंग कोड को उसी तरह से स्पष्ट कर सकते हैं जिस तरह से एनम कर सकते हैं। ऊपर के रूप में एक ही उदाहरण का उपयोग:

Enum.Parse(str, ignoreCase: true);

0

जहां मैं इस बात से सहमत हूं कि एनमेस जाने का अच्छा तरीका है, उन तरीकों में जहां आपके पास 2 विकल्प हैं (और सिर्फ दो विकल्प हैं, तो आपके पास एनम के बिना पठनीयता हो सकती है।)

जैसे

public void writeData(Stream data, boolean is_overwrite)

एनम से प्यार करें, लेकिन बूलियन भी उपयोगी है।


0

यह एक पुरानी पोस्ट पर एक देर से प्रविष्टि है, और यह पृष्ठ पर इतनी दूर है कि कोई भी इसे कभी नहीं पढ़ेगा, लेकिन चूंकि किसी ने भी यह नहीं कहा है ...।

एक इनलाइन टिप्पणी अप्रत्याशित boolसमस्या को हल करने के लिए एक लंबा रास्ता तय करती है। मूल उदाहरण विशेष रूप से जघन्य है: फ़ंक्शन डिक्लेरेशन में चर का नाम देने की कोशिश करना! यह कुछ इस तरह होगा

void writeData( DataObject data, bool use_append_mode );

लेकिन, उदाहरण के लिए, मान लें कि यह घोषणा है। फिर, अन्यथा एक अस्पष्टीकृत बूलियन तर्क के लिए, मैंने एक इनलाइन टिप्पणी में चर नाम रखा। तुलना

file.writeData( data, true );

साथ में

file.writeData( data, true /* use_append_mode */);

-1

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


-1

आपके उदाहरण में बूलियन के बजाय एनम का उपयोग विधि को अधिक पठनीय बनाने में मदद करता है। हालाँकि, यह C # में मेरी पसंदीदा इच्छा आइटम के लिए एक विकल्प है, जिसे मेथड कॉल में तर्क दिए गए हैं। यह वाक्य रचना:

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

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

सी # 3.0 कंस्ट्रक्टरों में नामित तर्कों की अनुमति देता है। मुझे नहीं पता कि वे तरीकों से ऐसा क्यों नहीं कर सकते।


एक दिलचस्प विचार। लेकिन क्या आप मापदंडों को फिर से व्यवस्थित कर पाएंगे? Omit पैरामीटर? कंपाइलर को यह कैसे पता चलेगा कि यदि यह वैकल्पिक था तो आप किस ओवरलोड के लिए बाध्य थे? इसके अलावा, क्या आपको सूची में सभी मापदंडों का नाम देना होगा?
ड्रू नोक

-1

बूलियन मूल्य true/ falseकेवल। इसलिए यह स्पष्ट नहीं है कि यह क्या दर्शाता है। Enumसार्थक नाम, हो सकता है जैसे OVERWRITE, APPENDआदि तो enums बेहतर हैं।

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