2009-04-22 11 views
5

मेरा प्रश्न यह है: सी # सुरक्षित में स्ट्रिंग concatenation है? यदि स्ट्रिंग कॉन्सटेनेशन अप्रत्याशित त्रुटियों की ओर जाता है, और स्ट्रिंगबिल्डर का उपयोग करके उस स्ट्रिंग कॉन्सटेनेशन को प्रतिस्थापित करने से उन त्रुटियों को गायब कर दिया जाता है, तो यह क्या इंगित कर सकता है?स्ट्रिंग कंसटेनेशन सी # में असुरक्षित, स्ट्रिंगबिल्डर का उपयोग करने की आवश्यकता है?

पृष्ठभूमि: मैं एक छोटी कमांड लाइन सी # अनुप्रयोग विकसित कर रहा हूं। यह कमांड लाइन तर्क लेता है, थोड़ा जटिल SQL क्वेरी करता है, और स्वरूपित XML फ़ाइल में डेटा की लगभग 1300 पंक्तियों को आउटपुट करता है।

मेरा प्रारंभिक कार्यक्रम हमेशा डीबग मोड में ठीक चलाएगा। हालांकि, रिलीज मोड में यह 750 वें एसक्यूएल परिणाम के बारे में होगा, और फिर एक त्रुटि के साथ मर जाएगा। त्रुटि यह थी कि डेटा का एक निश्चित स्तंभ पढ़ा नहीं जा सका, यहां तक ​​कि SqlDataReader ऑब्जेक्ट की Read() विधि के माध्यम से भी सच हो गया था।

यह समस्या कोड में सभी परिचालनों के लिए स्ट्रिंगबिल्डर का उपयोग करके तय की गई थी, जहां पहले "string1 + string2" था। मैं SQL क्वेरी लूप के अंदर स्ट्रिंग कॉन्सटेनेशन के बारे में बात नहीं कर रहा हूं, जहां स्ट्रिंगबिल्डर पहले से ही उपयोग में था। मैं कोड में पहले दो या तीन शॉर्ट स्ट्रिंग चर के बीच सरल concatenations के बारे में बात कर रहा हूँ।

मुझे यह धारणा थी कि सी # कुछ तारों को एक साथ जोड़ने के लिए स्मृति प्रबंधन को संभालने के लिए काफी स्मार्ट था। क्या मै गलत हु? या क्या यह किसी अन्य प्रकार की कोड समस्या का संकेत देता है?

+0

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

+0

मूल कोड: स्ट्रिंग filepath = पथ + fileroot + ".xml"; अपडेटेड कोड: स्ट्रिंग फ़ाइलपैथ = नया स्ट्रिंगबिल्डर (पथ) .एपेंड (फाइलरूट) .एपेंड ("। Xml")। ToString(); मैंने कई स्थानों पर इस तरह के बदलाव किए। ये मुख्य लूप से पहले हैं। मुख्य पाश के अंदर, मैं हमेशा XML फ़ाइल सामग्री बनाने के लिए स्ट्रिंगबिल्डर का उपयोग कर रहा हूं। (मैं एक्सएमएल एपीआई का उपयोग नहीं कर रहा हूं क्योंकि यह तेज़ था, और यह सिर्फ एक त्वरित और गंदा कार्यक्रम होना चाहिए।) –

उत्तर

7

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

+0

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

11

स्ट्रिंग कॉन्सटेनेशन सुरक्षित है हालांकि स्ट्रिंगबिल्डर का उपयोग करने से अधिक स्मृति गहन है यदि लूप में बड़ी संख्या में तारों को contatenating। और चरम मामलों में आप स्मृति से बाहर हो सकते हैं।

यह लगभग निश्चित रूप से आपके कोड में एक बग है।

शायद आप बहुत बड़ी संख्या में तारों का सामना कर रहे हैं। या शायद यह कुछ और पूरी तरह से अलग है।

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

-3

स्ट्रिंग्स को एक साथ जोड़ते समय मैं हमेशा स्ट्रिंगबिल्डर का उपयोग करता हूं। यह इसके लिए डिज़ाइन किया गया है और यह अधिक कुशल है कि "स्ट्रिंग 1 + स्ट्रिंग 2" का उपयोग कर रहा है।

+3

खराब सलाह। string1 + string2 कई परिस्थितियों में स्ट्रिंगबिल्डर से तेज़ है: स्ट्रिंगबिल्डर एक लूप में बड़ी संख्या में कॉन्सटेनेशन करते समय जीतता है। – Joe

+0

मुझे बताने के लिए धन्यवाद। मैंने पढ़ा था कि यह "सी # सीएलआर के माध्यम से" तेज था, लेकिन अगर ऐसा नहीं है, तो यह जानना अच्छा है। – patjbs

+0

मैंने स्ट्रिंगबिल्डर का उपयोग करने के बजाय "स्ट्र 1 + स्ट्र 2" के माध्यम से बहुत से परीक्षणों को चलाने और यहां तक ​​कि दो छोटे तारों को भी संयोजित किया है, वास्तव में धीमा है, या सबसे तेज़ नहीं है। और बाद में पढ़ने वाले कई उत्कृष्ट ब्लॉग आलेख उस निष्कर्ष से सहमत हैं। स्ट्र 1 + स्ट्र 2 का उपयोग करते समय एक आसान सुविधा हो सकती है और छोटे स्ट्रिंग कॉन्सटेनेशन पर महत्वपूर्ण प्रदर्शन प्रभाव नहीं पड़ता है, स्ट्रिंगबिल्डर निश्चित रूप से कोई भी बदतर नहीं है, और कॉन्सट की संख्या बढ़ने के साथ ही जीत जाएगी (जितना छोटा अंतर 4 है) – patjbs

3

स्ट्रिंग बिल्डर संस्करण बनाम कॉन्सटेनेशन संस्करण कितना समय लगेगा? यह संभव है कि डीबी से आपका कनेक्शन बंद हो रहा है। यदि आप बहुत अधिक संयम कर रहे हैं, तो मैं w/Stringbuilder जाऊंगा क्योंकि यह थोड़ा अधिक कुशल है।

1

एक कारण यह हो सकता है कि स्ट्रिंग्स अपरिवर्तनीय हैं। इसलिए जब आप एक जैसे ऑपरेशन करते हैं तो आप वास्तव में एक नई स्ट्रिंग बना रहे हैं।

एक अन्य संभावित कारण यह है कि स्ट्रिंग लंबाई एक int है इसलिए अधिकतम संभव लंबाई Int32.MaxValue या 2,147,483,647 है।

किसी भी मामले में स्ट्रिंगबिल्डर इस प्रकार के ऑपरेशन के लिए "स्ट्रिंग 1 + स्ट्रिंग 2" से बेहतर है। हालांकि, अंतर्निहित XML क्षमताओं का उपयोग करना भी बेहतर होगा।

0

यहाँ अंधेरे में मेरी शॉट ... .NET में

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

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

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

13

आपके प्रश्न का उत्तर करने के लिए: सी # (और .NET सामान्य रूप में) "सुरक्षित" है में स्ट्रिंग contatenation, लेकिन एक तंग पाश में यह कर आप का वर्णन के रूप में गंभीर स्मृति दबाव के कारण और दबाव की संभावना है कचरा कलेक्टर पर।

मुझे लगता है कि आप जिन त्रुटियों के बारे में बात करते हैं, वे कुछ प्रकार के संसाधन थकावट से संबंधित थे, लेकिन यदि आप अधिक जानकारी प्रदान कर सकते हैं तो यह उपयोगी होगा - उदाहरण के लिए, क्या आपको अपवाद मिला? क्या एप्लिकेशन असामान्य रूप से समाप्त हो गया था?

पृष्ठभूमि: नेट तार अपरिवर्तनीय हैं, इसलिए जब आप इस तरह की एक संयोजन कार्य करें:

string result = ""; 
result = "aaa" 
string temp1 = result + "bbb"; 
result = temp1; 
string temp2 = temp1 + "ccc"; 
result = temp2; 
string temp3 = temp2 + "ddd"; 
result = temp3; 
// ... 
result = tempN + x; 

इसका उद्देश्य:

var stringList = new List<string> {"aaa", "bbb", "ccc", "ddd", //... }; 
string result = String.Empty; 
foreach (var s in stringList) 
{ 
    result = result + s; 
} 

यह मोटे तौर पर निम्नलिखित के बराबर है उदाहरण पर जोर देना है कि लूप के आसपास हर बार एक नई अस्थायी स्ट्रिंग के आवंटन में परिणाम होता है।

चूंकि तार अपरिवर्तनीय हैं, रनटाइम में कोई वैकल्पिक विकल्प नहीं है, लेकिन प्रत्येक बार जब आप अपने परिणाम के अंत में एक और स्ट्रिंग जोड़ते हैं तो एक नई स्ट्रिंग आवंटित करने के लिए।

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

इस संयोग के अंत में आपके पास स्मृति में संग्रहीत निम्नलिखित तार होंगे (सादगी के लिए, कचरा कलेक्टर अभी तक नहीं चला है)।

string a = "aaa"; 
string b = "bbb"; 
string c = "ccc"; 
// ... 
string temp1 = "aaabbb"; 
string temp2 = "aaabbbccc"; 
string temp3 = "aaabbbcccddd"; 
string temp4 = "aaabbbcccdddeee"; 
string temp5 = "aaabbbcccdddeeefff"; 
string temp6 = "aaabbbcccdddeeefffggg"; 
// ... 

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

अनुशंसित दृष्टिकोण हमेशा StringBuilder का उपयोग करना है यदि आप कुछ स्ट्रिंग concatenations से अधिक कर रहे हैं।StringBuilder आपकी स्ट्रिंग को बनाने में आवश्यक आवंटन की संख्या को कम करने के लिए एक परिवर्तनीय बफर का उपयोग करता है।

+0

उत्कृष्ट उत्तर :) – patjbs

+4

मुझे यकीन है कि एक + बी + सी + डी ... एक ही कथन में मध्यवर्ती तार उत्पन्न नहीं करता है। यह स्ट्रिंग.कोनकैट की तरह काम करता है। – Joe

+0

जो: आप बिल्कुल सही हैं। मैं जवाब को सरल बनाने में बहुत दूर चला गया। मैंने इसे और अधिक वास्तविक रूप से सही बनाने के लिए एक लूप जोड़ा है। क्या वो बेहतर है? –

0

string.Concat(string[]) तारों को संयोजित करने का सबसे तेज़ तरीका है। यह लूप में उपयोग किए जाने पर प्रदर्शन में StringBuilder को कड़वाहट से मारता है, खासकर यदि आप प्रत्येक पुनरावृत्ति में StringBuilder बनाते हैं। यदि आप Google "सी # स्ट्रिंग प्रारूप बनाम स्ट्रिंगबिल्डर" या ऐसा कुछ करते हैं तो संदर्भों के बहुत सारे हैं। http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx आपको समय के बारे में एक विचारक देता है। यहाँ string.Join concatenation test जीतता है लेकिन मुझे विश्वास है क्योंकि string.Concat(string, string) का उपयोग अधिभारित संस्करण के बजाय किया जाता है जो एक सरणी लेता है। यदि आप एमएसआईएल कोड को देखते हैं जो विभिन्न तरीकों से उत्पन्न होता है तो आप देखेंगे कि हुड के नीचे क्या चल रहा है।

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

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