2010-05-17 12 views
23

निम्नलिखित में से कौन सा एक प्रदर्शन और मानक अभ्यास के लिए सबसे अच्छा wrt है। .NET आंतरिक रूप से इन दो कोड स्निपेट को कैसे प्रबंधित करता है?अन्यथा या वापसी?

Code1

If(result) 
{ 
    process1(); 
} 
else 
{ 
    process2(); 
} 

या कोड 2

If(result) 
{ 
    process1(); 
    return; 
} 
process2(); 
+2

महान सवाल, मैंने एक प्रश्न नहीं देखा है कि दो अलग-अलग दृष्टिकोणों के बीच इस तरह के घनिष्ठ प्रतियोगिता को उकसाया गया है। – Fenton

उत्तर

25

प्रदर्शन अंतर, यदि कोई है, तो किसी भी सामान्य मामले में नगण्य है।

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

मध्य में return के लिए वास्तविक कार्यान्वयन संभवतः विधि के अंत में कूदने की संभावना है, जहां विधि के लिए स्टैक फ्रेम को लपेटने के लिए कोड है, इसलिए यह संभव है कि अंतिम निष्पादन योग्य कोड दो कोड के लिए समान है।

+4

मैं विधि से एकल निकास बिंदु से सहमत हूं। – Ram

+0

मैं सहमत हूं। आपको यह विचार करना होगा कि संभावित रूप से साइड इफेक्ट हो सकता है, उदाहरण के लिए, यदि आपने इसे पकड़ने में किया है, तो आप अनजाने में ब्रेस के बाद कोड निष्पादित कर सकते हैं। – Doobi

+0

मैं इस सिद्धांत का पालन करने का प्रयास करता हूं कि पृष्ठ पर कोड के स्वरूपण को कोड की तार्किक संरचना को प्रतिबिंबित करना चाहिए। उपरोक्त कोड 2 इस तथ्य को अस्पष्ट करता है कि नीचे आधा "आभासी" अन्य ब्लॉक में है। इसे स्पष्ट करें। निकास के एक बिंदु के लिए – JeremyP

1

वापसी कोड से जो कुछ भी विधि अगर बयान में है, आगे कोई कोड निष्पादित किया जाएगा वापस जाने के लिए कारण होगा। वापसी के बिना बयान बस अगर कथन से बाहर हो जाएगा।

2

प्रदर्शन के बारे में नहीं कह सकता है, लेकिन कोड 1 मुझे बहुत स्पष्ट और अधिक तार्किक लग रहा है। if ब्लॉक के बीच में फ़ंक्शन से बाहर निकलना काफी उलझन में दिखाई देता है और इसे अनदेखा करना आसान है।

+0

तो आपको लगता है कि कोड 2 बहुत स्पष्ट दिखता है, लेकिन आपको यह पसंद नहीं है क्योंकि यह भ्रमित है? –

+0

@ एंड्रियास: ओह, टाइपो। मेरा मतलब कोड 1 था (और मेरा जवाब सही कर दिया है)। माफ़ कीजिये। –

4

अगर कोई आम कोड, अगर/बाकी ब्लॉक के बाद निष्पादित करने की आवश्यकता है कि, फिर विकल्प 1.

अगर-बाकी ब्लॉक विकल्प 2 एक समारोह में करने के लिए आखिरी बात है, तो है।

निजी तौर पर मैं हमेशा विकल्प 1. का उपयोग करते हैं वहाँ एक वापसी stateent है, यह बाद बाकी

3

ब्लॉक आप 2 संस्करण के शेष कोड के आसपास ब्रेसिज़ निकालने के लिए, यह है कि मैं वास्तव में क्या उपयोग करें तो आता है। मैं एक फ़ंक्शन के प्रारंभिक सत्यापन भाग को स्पष्ट करना पसंद करता हूं, और फिर मैं व्यवसाय पर उतर सकता हूं।

कहा जा रहा है, यह राय का विषय है। जब तक आप इसके बारे में सुसंगत हों, तब तक एक चुनें और इसके साथ चिपके रहें।

संपादित करें: प्रदर्शन के बारे में, उत्सर्जित आईएल बिल्कुल वही है। शैली के लिए एक या दूसरे को चुनें, या तो कोई जुर्माना नहीं है।

+0

मैंने कोड साफ़ किया। मुझे लगता है कि वह मूल रूप से मतलब था; मुझे नहीं लगता कि अनावश्यक दायरा वह था जो वह पूछ रहा था। – Will

+0

हाँ मैंने सोचा, मैं बस स्पष्ट होना चाहता था। – Blindy

32

निजी तौर पर मैं हमेशा यथाशीघ्र वापस जाने के लिए तो मैं की तरह कुछ के लिए जाना होगा की तरह: प्रदर्शन के साथ संबंध है

if (result) 
{ 
    // do something 
    return; 
} 

// do something if not result 

, मुझे शक है तो यह वास्तव में पठनीयता और व्यक्तिगत स्वाद के नीचे आता है eachother पर किसी भी फायदे हैं। मुझे लगता है कि .NET आपके पहले कोड ब्लॉक को उपरोक्त की तरह कुछ अनुकूलित करेगा।

+1

ब्याज से, आप 'ASAP वापस क्यों' करना पसंद करते हैं? क्या फायदा है? – JBRWilkinson

+1

@ जेबीआर विल्ककिन्सन: हालांकि छोटे अनुकूलन शायद लापरवाह है (जैसा कि कहा गया है) मुझे हमेशा लगता है कि यह काम करने के लिए * सही * तरीका है। उस विधि में क्यों जारी रखें जब आपके पास कोई अन्य व्यवसाय न हो? इसके परिणामस्वरूप आगे की प्रक्रिया हो सकती है जो अनावश्यक है। – James

+9

मैं स्पष्ट रूप से इस जवाब के पक्ष में हूं, कम से कम मामलों में जब परिणाम एक चेक है। कोड के गहरे घोंसले से बचने से कोड अधिक पठनीय और रखरखाव योग्य रहता है। इसके अलावा मैंने बहुत सारे डुप्लिकेट कोड को देखा है यदि/अन्य शाखाएं (निश्चित रूप से जरूरी नहीं)। – mattanja

1

मैं Code 1 का प्रयोग करेंगे, क्योंकि अगर मैं बाद में if बयान के बाद कुछ जोड़ने, मैं अभी भी सकारात्मक यह निष्पादित करेंगे हूँ, बिना मुझे जहां यह Code 2 में है से return खंड को दूर करने के लिए याद करने की जरूरत।

+0

उत्कृष्ट बिंदु। – JBRWilkinson

0

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

if(result) 
{ 
    process 1 
    return; 
} 

process 2 
0

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

if (con){ 
    ... 
    return; 
} 
if (other con){ 
    ... 
    return; 
} 
... 
return; 
1

दोनों शैलियों आम हैं, और धार्मिक युद्ध उन पर लड़े गए हैं। :-)

मैं सामान्य रूप से ऐसा करते हैं:

  • परीक्षा पद्धति अनुबंध अर्थ विज्ञान, उदा व्यक्त कर रहा है, तो वैधता के लिए इनपुट पैरामीटर्स की जाँच, फिर विकल्प 2.
  • अन्यथा चुनें 1.

चुनते हैं, तो विकल्प हालांकि, यकीनन एक और महत्वपूर्ण नियम "है जो अधिक पठनीय और/या अगले डेवलपर हैं जो पर लग रहा है के लिए पोषणीय है कोड?"।

प्रदर्शन अंतर नगण्य है, जैसा कि अन्य ने कहा है।

0

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

+0

लॉक नहीं हैं (माना जाता है कि आप लॉक का उपयोग कर रहे हैं {}) जब वे मौजूदा दायरे से बाहर हैं, तो() {} का उपयोग करने के समान ही स्वचालित रूप से रिलीज़ होते हैं? मैं कल्पना नहीं करता कि यह किसी अन्य तरीके से व्यवहार कर रहा है। –

1

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

दिनचर्या के लिए एक निकास बिंदु पर चिपकना एक अच्छा अभ्यास है।

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

अर्थात्:

if (date not set) return false; 
age = calculateAgeBasedOnDate(); 
if (age higher than 100) return false; 
...lots of code... 
return result; 
0

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

23

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

मैं कहूंगा कि दोनों के बीच चुनाव अर्थशास्त्र पर निर्भर करता है।

'अगर कुछ हालत सच है तो ऐसा करें, अन्यथा ऐसा करें' नक्शे को पूरी तरह से करें।

if (isLoggedIn) { 
    RedirectToContent(); 
} else { 
    RedirectToLogin(); 
} 

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

if (user == null) { 
    RedirectToLogin(); 
    return; 
} 

DisplayHelloMessage(user.Name); 

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

+3

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

0

अगर मुझे कहना है, तो मैं कहूंगा कि बेहतर अभ्यास "अंतर्निहित" के बजाय अन्यथा है। कारण यह है कि यदि कोई और आपके कोड को संशोधित करता है, तो वे आसानी से इसे देखकर पकड़ सकते हैं।

मुझे याद है कि प्रोग्रामिंग दुनिया में बड़ी बहस है कि आपके कोड में एकाधिक रिटर्न स्टेटमेंट होना चाहिए या नहीं। कोई कह सकता है कि यह बहुत भ्रम का स्रोत है क्योंकि यदि आपके पास "if" कथन के भीतर कई लूप हैं, और सशर्त रिटर्न हैं, तो इससे कुछ भ्रम हो सकता है।

मेरा सामान्य अभ्यास एक if-else कथन और एकल रिटर्न स्टेटमेंट होना है।

उदाहरण के लिए,

type returnValue; 
if(true) 
{ 
returnValue = item; 
} 
else 
returnValue = somethingElse; 

return returnValue; 

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

+0

यदि आप कार्य कर रहे हैं तो आसानी से यह देखने के लिए बहुत जटिल है कि एकाधिक निकास बिंदु कहां हैं, आपको एकाधिक निकास बिंदुओं की तुलना में बड़ी समस्याएं हैं। समारोह को तोड़ने की जरूरत है। – ICR

3

वे रिलीज मोड के लिए एक ही आईएल में संकलित होंगे (डीबग में कुछ अलग नॉप ऑपरेशंस हो सकते हैं ..) और इस तरह के कोई प्रदर्शन अंतर नहीं होगा। यह पूरी तरह से निर्भर है कि आप और आपकी टीम को लगता है कि कोड को पढ़ने में आसान है।

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

// C# 
public static void @elseif(bool isTrue) 
{ 
    if (isTrue) 
     Process1(); 
    else 
     Process2(); 
} 
// IL 
.method public hidebysig static void elseif(bool isTrue) cil managed 
{ 
    // Code size  15 (0xf) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: brfalse.s IL_0009 
    IL_0003: call  void elseif.Program::Process1() 
    IL_0008: ret 
    IL_0009: call  void elseif.Program::Process2() 
    IL_000e: ret 
} // end of method Program::elseif 


// C# 
public static void @earlyReturn(bool isTrue) 
{ 
    if (isTrue) 
    { 
     Process1(); 
     return; 
    } 
    Process2(); 
} 
// IL 
.method public hidebysig static void earlyReturn(bool isTrue) cil managed 
{ 
    // Code size  15 (0xf) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: brfalse.s IL_0009 
    IL_0003: call  void elseif.Program::Process1() 
    IL_0008: ret 
    IL_0009: call  void elseif.Program::Process2() 
    IL_000e: ret 
} // end of method Program::earlyReturn 
0

यह "परिणाम", "प्रक्रिया 1" और "प्रक्रिया 2" पर निर्भर करता है।

यदि प्रक्रिया 2 "परिणाम" का तार्किक परिणाम गलत है; आपको कोड 1 के लिए जाना चाहिए। यदि प्रक्रिया 1 और प्रक्रिया 2 समकक्ष विकल्प हैं तो यह सबसे पठनीय पैटर्न है।

if (do_A_or_B = A) 
    A() 
else 
    B() 

यदि परिणाम कुछ "न जाओ" हालत और "process1" है अगर "process2" का मुख्य कार्य है महज एक सफाई ऐसी शर्त पर की जरूरत आप कोड 2. का चयन करना चाहिए यह सबसे पठनीय पैटर्न है कार्यक्रम।

if (NOT can_do_B) 
{ 
    A() 
    return 
} 

B() 
0

यह संदर्भ पर निर्भर करता है।

यदि यह किसी फ़ंक्शन में है जो किसी मान की गणना करने पर है, तो जितनी जल्दी हो सके उस मान को वापस करें (विकल्प 2)। आप दिखा रहे हैं कि आपने जो काम किया है, वह कर चुके हैं, और जा रहे हैं।

यदि यह कोड है जो प्रोग्राम तर्क का हिस्सा है तो यह यथासंभव सटीक होना चाहिए (विकल्प 1)। कोई विकल्प 1 को देखकर आपको पता चलेगा कि यह मतलब है (यह या वह करें), जहां विकल्प 2 गलती हो सकती है (इस स्थिति में ऐसा करें हमेशा ऐसा करें - मैं इसे सिर्फ आपके लिए सही कर दूंगा!)। इससे पहले था।

इन्हें संकलित करते समय आमतौर पर वही होगा, लेकिन हमें प्रदर्शन में रूचि नहीं है। यह पठनीयता और रखरखाव के बारे में है।

2

यहाँ गार्ड खंड पर कुछ अतिरिक्त पढ़ने है: http://www.c2.com/cgi/wiki?GuardClause

एक अवधि मैंने कहा कि मुझे लगता है कि नहीं देखा था महत्वपूर्ण है - गार्ड खंड के प्रयोजन के पठनीयता को बढ़ाने के लिए है। एकल निकास विधियां "तीर" कोड की तरफ हो सकती हैं (जहां बयानों का घोंसला एक तीरहेड बनाता है)।

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