2009-03-19 19 views
9

लेबल और GOTO एस को खराब अभ्यास माना जाता है और जहां तक ​​मुझे पता है कि इसका उपयोग सी # में करने का कोई कारण नहीं है।सी # में लेबल का उपयोग क्या है?

सी # में लेबल का उपयोग क्या है?

+3

वे अन्य प्रोग्रामर को आपके कोड के बारे में शिकायत करने का एक कारण देते हैं :-) –

+0

संभावित डुप्लिकेट [क्या कोई अभी भी सी # में \ [goto \] का उपयोग करता है और यदि तो क्यों?] (http://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why) –

उत्तर

19

लेबल और गेटो के साथ कुछ भी गलत नहीं है। समस्या यह है कि लोग उनको दुर्व्यवहार करते हैं जो समस्या पैदा करते हैं।

एक लेबल की विशिष्ट उपयोग

OperationStart: 
    if (!TrySomeOperation()) { 
    if (MaybeFixOperation()) { 
     goto OperationStart; 
    } 
    } 

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

+0

मुझे लगता है कि यह सबसे आम उपयोग है गोटो का –

+5

"इस कोड के साथ स्वाभाविक रूप से गलत कुछ भी नहीं है" क्या आपका मतलब यह है कि यह बहुत पठनीय नहीं है? यदि आपने इसे लिखा था: जबकि (! TrySomeOperation() && MaybeFixOperation()) {} यह यह और अधिक स्पष्ट करता है कि आप (संभवतः असीमित) लूपिंग कर रहे हैं। – Aiua

+5

पाठक की आंखों में पठनीयता है। मैंने ठीक किया। – Perchik

7

सिर्फ इसलिए कि वे एक विवादित अभ्यास हैं, इसका मतलब यह नहीं है कि उनका उपयोग करने की कोई संभावना बंद हो। जबकि वे वास्तव में आवश्यक नहीं हो सकते हैं, वे कभी-कभी जाने का सबसे अच्छा तरीका होते हैं।

2

मुझे लगता है कि यह एक विपणन निर्णय था ..

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

+0

रिकॉर्ड: मैं एमएस नफरत नहीं हूं .. मैं सी # जितना अगला लड़का प्यार कर रहा हूं .. और मुझे लगता है कि यह लेबल और गेटो स्टेटमेंट जोड़ने के लिए एक स्मार्ट चाल था ... – Arcturus

0

मैंने कहीं पढ़ा है, ज्यादातर मामलों में गेटो का उपयोग आगे बढ़ने के लिए किया जाना चाहिए, इसलिए संभवतः केवल प्रारंभिक लूप समाप्ति के लिए और बाहरी लूप को जारी रखने के लिए सी # (जावा के विपरीत) में कोई लेबल लूप नहीं हैं। और कुछ एल्गोरिदम हैं जिन्हें संरचित तरीके से करने के बजाय गेटो के साथ सुंदर ढंग से व्यक्त किया जा सकता है।

+0

इस तरह मैं गेटोस का उपयोग करता हूं। घोंसला के लिए लूप, कभी-कभी इसके बजाय कुछ लेबल मिलना आसान होता है यह पता लगाने की कोशिश कर रहा है कि किस लूप को तोड़ना है। – Perchik

0

कभी-कभी एक अच्छी तरह से रखा गया 'गोटो' अन्य तकनीकों की तुलना में अधिक सुरुचिपूर्ण/पठनीय है। जब उन्हें जरूरत नहीं होती है तो गेटो को चारों ओर रखना एक निश्चित अभ्यास है। हमेशा की तरह, प्रत्येक स्थिति सावधानी से तय किया जाना चाहिए।

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

फिर भी, 'सीओ की तुलना में सी # में गेटो कम उपयोगी हो गया है। उदाहरण के लिए, अपवाद हैंडलिंग का उचित उपयोग कुछ परिदृश्यों में' गोटो 'की आवश्यकता को रोक सकता है।

0

लेबल का उपयोग goto का समर्थन करना है। goto के रूप में खराब हो सकता है, यदि आपके पास भाषा में goto है, तो आपको लेबल की आवश्यकता है। goto के बिना, लेबल वास्तव में सी # में बेकार हैं।

6

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

कभी-कभी समस्या डोमेन में कई राज्य माचियां होती हैं, (उदाहरण के लिए दूरसंचार प्रोटोकॉल को अक्सर परिमित राज्य मशीनों द्वारा परिभाषित किया जाता है), अधिकांश समय आप परिमित राज्य मशीन को अक्सर नहीं देखते हैं।

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

+0

डीएफए वास्तव में काफी उपयोग किया जाता है, आम तौर पर इन्हें टोकननाइज़र और पार्सर्स में उपयोग किया जाता है। इस दृष्टिकोण से बड़े पैमाने पर तरीकों का कारण बन जाएगा ... आपको पता है कि यदि आपके पास आईएल में बहुत बड़ी विधि है, तो इसे .NET रनटाइम द्वारा अनुकूलित नहीं किया जाएगा, है ना? विभिन्न कारणों से यदि आप मुझसे पूछते हैं तो एक डीएफए के लिए राज्य पैटर्न को संकलित करना बेहतर होता है - भले ही यह मशीन जेनरेट कोड हो। – atlaste

2

लेबल बेकार हैं, वे कुछ भी नहीं।

का उपयोग करना goto एक बुरा व्यवहार माना जाता है। नेस्टेड छोरों को तोड़ते:

foreach(...) { 
    foreach(...) { 
    if(...) { 
     goto OuterLabel; 
    } 
    } 
} 
OuterLabel: 

ऐसी स्थिति में break कथन का उपयोग बस सबसे भीतरी पाश टूट जाएगा लेकिन वहाँ एक मामले में जहां यह टाला नहीं जा सकता है।

+1

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

+0

सहमत है, एक अलग विधि का उपयोग करना एक अच्छा तरीका है, क्योंकि 'वापसी' कथन पूरी विधि से बाहर निकलने में सक्षम है। –

+5

कुछ लोग (स्वयं शामिल) उन्हें बनाने के लिए विधियों को बनाना पसंद नहीं करते हैं। – Perchik

1

उनके बिना स्विच स्टेटमेंट करना मुश्किल है।

+0

यह है? मुझे लगता है कि आप एक उदाहरण दे सकते हैं? – Blorgbeard

+0

केस और डिफ़ॉल्ट विवरण लेबल हैं। आप इसे देख सकते हैं: स्विच (x) { केस 1: यदि (oneEqualsTwo) goto case 2; ब्रेक; केस 2: ब्रेक; } यह सी #: http://www.csharpfriends.com/Spec/index.aspx?specID=15.7.2.htm – mancaus

0

जबकि सिद्धांत रूप में मेरा मानना ​​है कि goto बयान के लिए वैध का उपयोग करता है देखते हैं, व्यवहार में मैं सी # में विकसित किया गया है कि के बाद से यह पहली बार जारी किया गया था और मुझे नहीं पता था यह एक goto बयान था अब तक।

2

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

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

0

यदि (दर्शक.LikesGoTo == सत्य) { गोटो LabelThatSupportGoTo; } else { गोटो LabelForRejectGoTo; }

+0

के लिए ईसीएमए स्पेक में स्पष्ट हो गया है [इस आलेख] (http: LabelForRejectGoTo के लिए //www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html)। – Ben

2

क्यों नहीं है?

कारण वास्तव में बहुत सरल है। कोडांतरक और आईएल for, do, break, continue और while जैसे उन्नत निर्देश समर्थन नहीं करते। स्पष्ट रूप से, कोड जो लूप (या अधिक आम तौर पर: शाखाएं) शाखाओं में संकलित किया जाता है। goto और label एक बहुत ही शाब्दिक शाखा है।

ध्यान दें कि आप आसानी से उन सभी कॉन्ट्रैप्शन को लागू नहीं कर सकते हैं जिन्हें मैं आसानी से 'गोटो' के बिना सोच सकता हूं - भले ही आमतौर पर बेहतर विकल्प होते हैं (इस बिंदु पर मैं यह इंगित करना चाहता हूं कि डिजाइन पैटर्न जैसे हैं State pattern)।

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

संकलक पीओवी

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

यहां समस्या है। यदि आपके पास while लूप है, तो for लूप या foreach पाश, यह निश्चित रूप से सामान्यीकृत पैटर्न उत्पन्न करेगा। आखिरकार, लूप आपके कोड में नंबर एक चीज हैं जिन्हें अनुकूलित किया जा सकता है। हालांकि, अगर आप अजीब शाखाओं का उपयोग कर रहे हैं, तो वे अनुकूलित नहीं होंगे - बस क्योंकि यह मानकीकृत पैटर्न के लिए सामान्यीकृत नहीं किया जाएगा और इसलिए पैटर्न मैचर द्वारा नहीं उठाया जाएगा।

यह टिप्पणी कोड पैटर्न की अनुमानितता के बारे में नहीं है - यह डेटा प्रवाह की भविष्यवाणी के बारे में भी है। दोबारा, यदि यह अनुमान लगाया जा सकता है, तो आपका कंपाइलर ऐसा नहीं कर सकता है अगर यह नहीं है। विभिन्न मामलों में, break और continue जैसे निर्माण भी अधिक अप्रत्याशित शाखाओं का कारण बनेंगे; लेबल और goto आपको वहां और आसानी से ले जाएगा। नतीजा वही है: यदि ऐसा होता है तो आपका प्रदर्शन भुगतना होगा।

तो यह सच है कि सभी कंपाइलर्स एक विशिष्ट रूप की शाखाओं में लूप बदलते हैं। आईएल कंपाइलर एक एसएसए कंपाइलर है, जैसे कि एलएलवीएम। चांडलर का यह वीडियो इस बात के बारे में एक या दो बताता है कि यह कैसे काम करता है: https://www.youtube.com/watch?v=FnGCDLhaxKU

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