2012-05-19 22 views
6

मुझे पता है कि string अपरिवर्तनीय है और StringBuilder उत्परिवर्तनीय है। लेकिन क्या कोई निम्नलिखित कोड आउटपुट समझा सकता है? चूंकि दोनों संदर्भ प्रकार हैं, उनके पास अलग-अलग परिणाम क्यों हैं?स्ट्रिंग और स्ट्रिंगबिल्डर के बीच क्या अंतर है?

String s1 = "hello"; 
String s2 = "hello"; 
Console.WriteLine(s1 == s2); //true 
Console.WriteLine(Object.ReferenceEquals(s1, s2)); //true 

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 
Console.WriteLine(sb1 == sb2); //false 
Console.WriteLine(Object.ReferenceEquals(sb1, sb2)); //false 
+1

आप दो अलग-अलग 'स्ट्रिंगबिल्डर' ऑब्जेक्ट संदर्भों की तुलना कर रहे हैं। वे दो अलग-अलग वस्तुएं हैं। – birryree

+0

+1, न केवल एक उत्कृष्ट प्रश्न के लिए, बल्कि इसे स्पष्ट रूप से पूछने के लिए कोड के पूर्ण नमूने के साथ, यह स्पष्ट रूप से पूछने के लिए। –

+1

इस प्रश्न में वास्तव में 'स्ट्रिंगबिल्डर' के साथ कुछ लेना देना नहीं है। यह वास्तव में है "दो स्ट्रिंग चर के साथ दो स्ट्रिंग वैरिएबल प्रारंभ क्यों किए जाते हैं जिसमें एक ही वर्ण अनुक्रम एक ही वस्तु के रूप में तुलना करता है"? –

उत्तर

10

के बाद से:

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 
Console.WriteLine(sb1 == sb2); //false 

इस तरह आप उनके मूल्यों की तुलना कर सकते है दोनों संदर्भ प्रकार हैं, उनके पास अलग-अलग परिणाम क्यों हैं?

क्योंकि string ऑब्जेक्ट्स अत्यधिक अनुकूलित हैं। विशेष रूप से, चूंकि वे अपरिवर्तनीय हैं, इसलिए उन्हें डुप्लिकेशंस को रोकने के लिए कंपाइलर द्वारा प्रशिक्षित किया जा सकता है।

यदि आपके पास दो अलग-अलग string ऑब्जेक्ट्स हैं जो दोनों वर्णों की सटीक समान स्ट्रिंग का प्रतिनिधित्व करते हैं (जैसा कि आपके उदाहरण में है), संकलक वास्तविक स्ट्रिंग ऑब्जेक्ट का केवल एक उदाहरण पहचान लेगा और बनाए रखेगा।

परिणाम यह है कि s1 और s2 ऑब्जेक्ट्स वास्तव में वही ऑब्जेक्ट हैं जहां तक ​​संकलक का संबंध है और यहां तक ​​कि स्मृति में उसी स्थान का संदर्भ भी है।

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

उसी प्रकार की चीज StringBuilder ऑब्जेक्ट्स के लिए होती है, क्योंकि वे अपरिवर्तनीय नहीं हैं। वे आपको एक स्ट्रिंग ऑब्जेक्ट को संशोधित करने की अनुमति देने के लिए डिज़ाइन किए गए हैं, और इस तरह, अनुकूलन बहुत अधिक समझ में नहीं आता है। यही कारण है कि आपकी sb1 और sb2 वस्तुओं को वास्तव में दो अलग-अलग वस्तुओं के रूप में देखा जाता है।

अंगूठे का नियम काफी सरल है: डिफ़ॉल्ट रूप से string का उपयोग करें, या जब आप अक्षरों की एक अपरिवर्तनीय स्ट्रिंग चाहते हैं। केवल StringBuilder का उपयोग करें जब आप एक ही स्ट्रिंग को कई बार संशोधित करना चाहते हैं, तो लूप या कोड के अन्य अपेक्षाकृत छोटे सेक्शन में कहें।

प्रासंगिक पढ़ने: Optimizing C# String Performance

+0

यह सही समझ में आता है। – GLP

1

जब आप निम्नलिखित आप तुलना कर रहे हैं दो अलग अलग StringBuilder उनके मूल्यों नहीं वस्तुओं कर रहे हैं:

Console.WriteLine(sb1.ToString() == sb2.ToString()); 
4

जब आप

String s1 = "hello"; 
String s2 = "hello"; 

संकलक बहुत चालाक पता चला है कि दो तार कर रहे हैं (और हमेशा रहेंगे) समान है की घोषणा, तो यह "hello" केवल एक बार संग्रहीत करता है और बनाता है s1 और s2 समान भौतिक स्मृति के लिए उपनाम के रूप में। बाद में, जब आप समानता के लिए परीक्षण करते हैं, तो दोनों बराबर होते हैं क्योंकि वे अनिवार्य रूप से एक ही चर होते हैं।

दूसरी ओर, जब आप यह घोषणा करते

StringBuilder sb1 = new StringBuilder("hello"); 
StringBuilder sb2 = new StringBuilder("hello"); 

संकलक दो चर बनाता है (वे दोनों परिवर्तनशील हैं, लेकिन एक ही मूल्य के लिए प्रारंभ होता है क्योंकि)।यह स्ट्रिंग "hello" उनमें से प्रत्येक में कॉपी करता है, लेकिन अब 2 प्रतियां हैं, क्योंकि प्रत्येक को बाद में बदला जा सकता है। तो भले ही उनकी सामग्री समान हों, वे 2 अलग-अलग संस्थाएं हैं जो विभिन्न भौतिक स्मृति स्थानों में रहते हैं, इसलिए ऑब्जेक्ट समानता के परीक्षण विफल हो जाते हैं।

2

डिफ़ॉल्ट रूप से, जब दो संदर्भ-प्रकार वस्तुओं की तुलना की जाती है, तो परिणाम सत्य केवल तभी होता है जब दोनों संदर्भ बराबर हों, जिसका अर्थ है कि दोनों ऑपरेटरों को ऑब्जेक्ट के उसी उदाहरण का संदर्भ देना चाहिए। चूंकि sb1 और sb2 द्वारा संदर्भित ऑब्जेक्ट्स दो अलग-अलग ऑब्जेक्ट्स हैं, स्ट्रिंगबिल्डर की तुलना में परिणाम गलत है।

लेकिन स्ट्रिंग क्लास समानता ऑपरेटर को इस तरह से ओवरराइड करता है, कि यह वस्तुओं को उनके संदर्भों से तुलना नहीं करता है, लेकिन उनके मूल्यों से, क्योंकि यह व्यवहार प्रोग्रामर द्वारा बहुत सहज और अपेक्षित है। यह बताता है कि क्यों s1 == s2 सत्य लौटाता है।

ऑब्जेक्ट। रेफरेंस एक्वाल्स (एस 1, एस 2) भी सही लौटाता है (हालांकि ऐसा लगता है कि एस 1 और एस 2 संदर्भ स्ट्रिंग के विभिन्न उदाहरण हैं) को string interning कहा जाता है। इसका कारण यह है कि सीएलआर प्रत्येक स्ट्रिंग अक्षर (जैसे कि "हेलो" और "हेलो") के सभी घटनाओं को केवल एक बार प्रति स्ट्रिंग के आंतरिक पूल में रखता है, इसलिए एस 1 और एस 2 वास्तव में स्ट्रिंग "हेलो" । यह संभव है, क्योंकि स्ट्रिंग अपरिवर्तनीय हैं।

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