2009-05-07 12 views
17

मैं एक स्ट्रिंग के लिए एक विधि में एक StringBuilder वस्तु का उपयोग कर निर्माण कर रहा हूँ, तो यह भावना को बनाना होगा:स्ट्रिंग या स्ट्रिंगबिल्डर वापसी मान?

वापसी StringBuilder वस्तु, और बुला कोड कॉल ToString जाने()?

return sb; 

या ToString() को कॉल करके स्ट्रिंग को वापस करें।

return sb.ToString(); 

मुझे लगता है कि अगर हम छोटे, या बड़े तार लौट रहे हैं तो मुझे कोई फर्क पड़ता है। प्रत्येक मामले में क्या उचित होगा? अग्रिम में धन्यवाद।

संपादित करें: मैं कॉलिंग कोड में स्ट्रिंग को और संशोधित करने की योजना नहीं बना रहा, लेकिन अच्छी बात कॉलिन बर्नेट।

मुख्य रूप से, क्या स्ट्रिंगबिल्डर ऑब्जेक्ट, या स्ट्रिंग को वापस करने के लिए यह अधिक कुशल है? क्या स्ट्रिंग का संदर्भ वापस आ जाएगा, या एक प्रतिलिपि?

उत्तर

21

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

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

ने कहा। आप परावर्तक साथ StringBuilder.ToString को देखें, तो:

public override string ToString() 
{ 
    string stringValue = this.m_StringValue; 
    if (this.m_currentThread != Thread.InternalGetCurrentThread()) 
    { 
     return string.InternalCopy(stringValue); 
    } 
    if ((2 * stringValue.Length) < stringValue.ArrayLength) 
    { 
     return string.InternalCopy(stringValue); 
    } 
    stringValue.ClearPostNullChar(); 
    this.m_currentThread = IntPtr.Zero; 
    return stringValue; 
} 

आप इसे एक प्रतिलिपि कर सकते हैं देख सकते हैं लेकिन यदि आप इसे StringBuilder साथ संशोधित तो यह तो एक प्रतिलिपि बनाने जाएगा (यह है कि मैं क्या की बात बता सकते हैं है m_current थ्रेड इसलिए है क्योंकि संलग्न करें इसे जांचें और अगर यह वर्तमान थ्रेड को मेल नहीं खाती है तो इसकी प्रतिलिपि बनाई जाएगी)।

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

अद्यतन

System.String है एक वर्ग है जो इसे एक संदर्भ प्रकार (मान प्रकार के रूप में विरोध किया) तो है का मतलब है "स्ट्रिंग foo," अनिवार्य रूप से एक सूचक है। (जब आप किसी विधि में एक स्ट्रिंग पास करते हैं तो यह पॉइंटर पास करता है, प्रतिलिपि नहीं।) सिस्टम। स्ट्रिंग mscorlib के अंदर उत्परिवर्तनीय है लेकिन इसके बाहर अपरिवर्तनीय है, इस प्रकार स्ट्रिंगबिल्डर एक स्ट्रिंग में हेरफेर कर सकता है।

तो जब ToString() कहा जाता है तो यह संदर्भ द्वारा अपनी आंतरिक स्ट्रिंग ऑब्जेक्ट देता है। इस बिंदु पर आप इसे संशोधित नहीं कर सकते क्योंकि आपका कोड mscorlib में नहीं है। M_current थ्रेड फ़ील्ड को शून्य पर सेट करके स्ट्रिंगबिल्डर पर कोई और ऑपरेशन स्ट्रिंग ऑब्जेक्ट की प्रतिलिपि बनाने का कारण बनता है, इसलिए इसे और संशोधित किया जा सकता है जो इसे ToString() में लौटाई गई स्ट्रिंग ऑब्जेक्ट को संशोधित नहीं करता है। इस पर विचार करें:

StringBuilder sb = new StringBuilder(); 
sb.Append("Hello "); 

string foo = sb.ToString(); 

sb.Append("World"); 

string bar = sb.ToString(); 

StringBuilder अंत foo पर तो एक प्रति नहीं किया है तो हो सकता है "नमस्ते दुनिया" क्योंकि StringBuilder इसे संशोधित। लेकिन चूंकि उसने एक प्रतिलिपि बनाई है तो foo अभी भी "हैलो" है और बार "हैलो वर्ल्ड" है।

क्या यह पूरी वापसी/संदर्भ वस्तु को स्पष्ट करता है?

+0

@ स्कीप्पीफायर दक्षता के बारे में पूछ रहा है। –

+0

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

+1

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

5

मुझे नहीं लगता कि प्रदर्शन इस प्रश्न में एक कारक होना चाहिए। किसी भी तरह से कोई व्यक्ति sb.ToString() को कॉल करने जा रहा है ताकि आप कहीं भी हिट ले सकें।

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

यदि यह सार्वजनिक एपीआई का हिस्सा है तो मैं निर्माता के बजाय स्ट्रिंग लौटने की ओर झुकता हूं।

+0

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

+1

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

+0

माइकल, उस टिप्पणी में मेरा एकमात्र बिंदु यह था कि "कोई एसबी कॉल करने जा रहा है।ToString() "मध्यवर्ती प्रतिलिपि का बिंदु गुम है जो प्रदर्शन को प्रभावित करेगा। कभी-कभी, हाँ, आप बेहतर एपीआई होने के लिए हिट लेना चाहेंगे या" स्ट्रिंग या स्ट्रिंगबिल्डर "के अलावा समाधान ढूंढने के लिए प्रेरित हो सकते हैं। –

3

मैं कहूंगा कि विधि sb.ToString() को वापस करनी चाहिए। यदि स्ट्रिंगबिल्डर() ऑब्जेक्ट के निर्माण के आस-पास के तर्क को भविष्य में बदलना चाहिए तो यह मुझे समझ में आता है कि यह विधि में बदल दिया गया है जो प्रत्येक परिदृश्य में नहीं है जो विधि को कॉल करता है और फिर कुछ और करने के लिए चला जाता है

0

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

अन्य तकनीकी विचार हैं, लेकिन यह उच्चतम स्तर की चिंताओं है।

1

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

इस पल के लिए इसके बारे में सोचने पर, जवाब बहुत स्पष्ट है। पूछने का सवाल जो वापस किया जाना चाहिए वास्तव में सवाल का जवाब दें। वापसी वस्तु एक स्ट्रिंग होना चाहिए। इसका कारण यह है कि यदि आप सवाल पूछ रहे हैं, "स्ट्रिंगबिल्डर ऑब्जेक्ट को वापस करने का कोई कारण है जब कोई स्ट्रिंग करेगा?" तो जवाब नहीं है। यदि कोई कारण था, तो स्ट्रिंग लौटने से प्रश्न बाहर हो जाएगा, क्योंकि स्ट्रिंगबिल्डर के तरीकों और गुणों की आवश्यकता होती है।

1

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

1

मैं लगभग सभी स्थितियों में string वापस कर दूंगा, खासकर यदि विधि सार्वजनिक एपीआई का हिस्सा है।

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

1

के बाद से अपने इसे अब और संशोधित करने के लिए नहीं जा रहा

return sb.ToString(); 

सबसे कुशल होना चाहिए

1

वापसी sb.ToString()। आपकी विधि को केवल हाथ में ध्यान केंद्रित करना चाहिए (इस मामले में मुझे एक स्ट्रिंग बनाएं) और आगे आईएमओ में हेरफेर करने के लिए वापस नहीं किया जाना चाहिए, आप इसे हल करने वाले सभी प्रकार की समस्याओं में शामिल हो सकते हैं।

3

StringBuilder आपकी विधि का कार्यान्वयन विवरण है। जब तक यह एक प्रदर्शन समस्या न हो जाए तब तक आपको स्ट्रिंग वापस करनी चाहिए, जिस बिंदु पर आपको एक और पैटर्न (जैसे visitor Pattern) का पता लगाना चाहिए जो आपको संकेत प्रदान करने में मदद कर सकता है और आंतरिक कार्यान्वयन निर्णयों से आपकी रक्षा कर सकता है।

स्ट्रिंग हमेशा ढेर में संग्रहीत होते हैं, इसलिए वापसी का प्रकार स्ट्रिंग होने पर आपके पास एक संदर्भ वापस आ जाएगा। हालांकि, आप समान संदर्भों के दो समान तारों पर गिनती नहीं कर सकते हैं। आम तौर पर, स्ट्रिंग के बारे में सोचना सुरक्षित है जैसे कि यह एक मूल्य प्रकार था, भले ही यह वास्तव में एक संदर्भ प्रकार है।

+1

+1 –

0

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

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

  • कोई संबंधित समस्या नहीं^_^