2012-02-03 14 views
115

नीचे दिए गए कोड में प्लस साइन का उपयोग करते समय कितने स्ट्रिंग ऑब्जेक्ट बनाए जाएंगे?प्लस साइन का उपयोग करते समय कितने स्ट्रिंग ऑब्जेक्ट बनाए जाएंगे?

String result = "1" + "2" + "3" + "4"; 

यदि यह नीचे था, तो मैंने तीन स्ट्रिंग ऑब्जेक्ट्स: "1", "2", "12" कहा होगा।

String result = "1" + "2"; 

मुझे यह भी पता है कि स्टिंग ऑब्जेक्ट्स को प्रदर्शन सुधार के लिए स्ट्रिंग इंटरनेशनल पूल/टेबल में कैश किया गया है, लेकिन यह सवाल नहीं है।

+0

स्ट्रिंग्स केवल प्रशिक्षु कर रहे हैं जब आप स्पष्ट रूप String.Intern फोन देखें। –

+7

@ जोहेइट: क्या वे हैं? –

+13

काफी नहीं। सभी स्ट्रिंग अक्षर स्वचालित रूप से प्रशिक्षित होते हैं। स्ट्रिंग ऑपरेशंस के परिणाम नहीं हैं। –

उत्तर

161

आश्चर्य की बात है, यह निर्भर करता है।

आप एक विधि में ऐसा करते हैं तो:

void Foo() { 
    String one = "1"; 
    String two = "2"; 
    String result = one + two + "34"; 
    Console.Out.WriteLine(result); 
} 

तो संकलक के रूप में @Joachim (उसे करने के लिए +1 Btw) जवाब String.Concat का उपयोग कर कोड का उत्सर्जन हो रहा है।

हैं तो आप उन्हें के रूप में परिभाषित, जैसे स्थिरांक:

const String one = "1"; 
const String two = "2"; 
const String result = one + two + "34"; 

या के रूप में शाब्दिक, मूल प्रश्न में के रूप में:

String result = "1" + "2" + "3" + "4"; 

तो संकलक उन + संकेत दूर अनुकूलित करेंगे । यह बराबर है करने के लिए:

const String result = "1234"; 

इसके अलावा, संकलक बाहरी निरंतर भाव निकाल देंगे, और केवल उन्हें फेंकना अगर वे इस्तेमाल किया या संपर्क में हैं। उदाहरण के लिए, इस कार्यक्रम:

const String one = "1"; 
const String two = "1"; 
const String result = one + two + "34"; 

public static void main(string[] args) { 
    Console.Out.WriteLine(result); 
} 

केवल उत्पन्न करता है एक string- ("1234" के बराबर) निरंतर resultone और two परिणामस्वरूप आईएल में दिखाई नहीं देते हैं।

ध्यान रखें कि रनटाइम पर और अधिक अनुकूलन हो सकते हैं। मैं सिर्फ आईएल द्वारा उत्पादित किया जा रहा हूँ।

अंत में, इंटर्निंग के संबंध में, स्थिरांक और शाब्दिकों को प्रशिक्षित किया जाता है, लेकिन मूल्य जो इंटर्न किया जाता है वह आईएल में परिणामी स्थिर मूल्य है, शाब्दिक नहीं। इसका मतलब यह है कि आप अपेक्षाकृत कम स्ट्रिंग ऑब्जेक्ट्स प्राप्त कर सकते हैं, क्योंकि कई समान रूप से परिभाषित स्थिरांक या अक्षर वास्तव में एक ही वस्तु होंगे! इस का पालन करते हुए दर्शाया गया है:

public class Program 
{ 
    private const String one = "1"; 
    private const String two = "2"; 
    private const String RESULT = one + two + "34"; 

    static String MakeIt() 
    { 
     return "1" + "2" + "3" + "4"; 
    } 

    static void Main(string[] args) 
    { 
     string result = "1" + "2" + "34"; 

     // Prints "True" 
     Console.Out.WriteLine(Object.ReferenceEquals(result, MakeIt())); 

     // Prints "True" also 
     Console.Out.WriteLine(Object.ReferenceEquals(result, RESULT)); 
     Console.ReadKey(); 
    } 
} 

मामले में जहां तार एक पाश में concatenated रहे हैं (या अन्य प्रकार गतिशील), तो आप संयोजन प्रति एक अतिरिक्त तार के साथ खत्म।2 स्थिरांक + 10 पुनरावृत्तियों प्रत्येक एक नया स्ट्रिंग उदाहरण है, जिसके परिणामस्वरूप: उदाहरण के लिए, निम्नलिखित 12 स्ट्रिंग उदाहरणों बनाता

public class Program 
{ 
    static void Main(string[] args) 
    { 
     string result = ""; 
     for (int i = 0; i < 10; i++) 
      result += "a"; 
     Console.ReadKey(); 
    } 
} 

लेकिन (यह भी आश्चर्यजनक रूप से), कई लगातार concatenations एक भी बहु में संकलक द्वारा संयोजित किया जाता है स्ट्रिंग concatenation। उदाहरण के लिए, यह प्रोग्राम केवल 12 स्ट्रिंग उदाहरण उत्पन्न करता है! ऐसा इसलिए है क्योंकि "Even if you use several + operators in one statement, the string content is copied only once."

public class Program 
{ 
    static void Main(string[] args) 
    { 
     string result = ""; 
     for (int i = 0; i < 10; i++) 
      result += "a" + result; 
     Console.ReadKey(); 
    } 
} 
+0

स्ट्रिंग परिणाम = "1" + "2" + तीन + चार के बारे में क्या; जहां दो और तीन स्ट्रिंग तीन = "3" की तरह घोषित किए जाते हैं; स्ट्रिंग चार = "4" ;? –

+0

यहां तक ​​कि एक स्ट्रिंग में परिणाम भी। मैंने खुद को दोबारा जांचने के लिए लिंककैड के माध्यम से भाग लिया। –

+0

@ विलियम - स्ट्रिंग परिणाम = "1" + "2" + तीन + चार परिणामस्वरूप एक कंपाइलर त्रुटि होगी। यदि आपका मतलब है "1" + "2" + 3 + 4 '3' और '4' तारों के रूप में लिया जाएगा। आप बाहर निकलना और कुछ सामग्री पढ़ना चाहेंगे कि .NET स्ट्रिंग के साथ कैसे काम करता है। –

13

एक, क्योंकि वे स्थैतिक हैं, संकलक संकलन समय पर एक स्ट्रिंग में इसे अनुकूलित करने में सक्षम होंगे।

यदि वे गतिशील थे, तो उन्हें String.Concat(string, string, string, string) पर एक ही कॉल में अनुकूलित किया गया होगा।

23

मुझे एमएसडीएन में जवाब मिला। एक।

How to: Concatenate Multiple Strings (C# Programming Guide)

कड़ी एक और स्ट्रिंग के अंत करने के लिए एक स्ट्रिंग जोड़कर की प्रक्रिया है। जब आप + ऑपरेटर का उपयोग करके स्ट्रिंग अक्षर या स्ट्रिंग स्थिरांक को संयोजित करते हैं, तो कंपाइलर एक स्ट्रिंग बनाता है। कोई रन टाइम कॉन्सटेनेशन नहीं होता है। हालांकि, स्ट्रिंग चर केवल रन टाइम पर संयोजित किया जा सकता है। इस मामले में, आपको विभिन्न दृष्टिकोणों के प्रदर्शन प्रभाव को समझना चाहिए।

22

बस एक। सी # संकलक स्ट्रिंग स्थिरांक गुना होगा और इसलिए यह अनिवार्य रूप से

String result = "1234"; 
+0

मैंने सोचा जब भी आप इसका उपयोग करते हैं, यह एक स्ट्रिंग ऑब्जेक्ट बनाता है। सामान्य रूप से –

+1

@ विलियम। लेकिन निरंतर फोल्डिंग अनावश्यक इंटरमीडिएट चरणों को हटा देगा – JaredPar

13

मुझे शक है यह किसी भी मानक या कल्पना द्वारा अनिवार्य है करने के लिए नीचे संकलित करता है। एक संस्करण दूसरे से कुछ अलग कर सकता है।

+3

यह वीएस 2008 और 2010 के लिए माइक्रोसॉफ्ट के सी # कंपाइलर के लिए कम से कम दस्तावेज व्यवहार है (देखें @ डेविड-स्ट्रैटन का जवाब)। उस ने कहा, आप सही हैं- जहां तक ​​मैं त्वरित जानकारी से कह सकता हूं, सी # spec यह निर्दिष्ट नहीं करता है और इसे शायद कार्यान्वयन विस्तार माना जाना चाहिए। –

86

क्रिस शाइन का जवाब बहुत अच्छा है। स्ट्रिंग कॉन्सटेनेशन ऑप्टिमाइज़र लिखने वाले व्यक्ति के रूप में मैं केवल दो अतिरिक्त दिलचस्प अंक जोड़ूंगा।

पहला यह है कि कॉन्सटेनेशन ऑप्टिमाइज़र अनिवार्य रूप से दोनों कोष्ठक और बाएं सहयोगीता को अनदेखा करता है जब यह सुरक्षित रूप से ऐसा कर सकता है। मान लें कि आपके पास एक विधि एम() है जो एक स्ट्रिंग देता है। यदि आप कहते हैं:

string s = M() + "A" + "B"; 

तो संकलक कारण है कि इसके अलावा ऑपरेटर साहचर्य छोड़ दिया है, और इसलिए इस रूप में ही है:

string s = ((M() + "A") + "B"); 

लेकिन इस:

string s = "C" + "D" + M(); 

है

string s = (("C" + "D") + M()); 

ताकि निरंतर स्ट्रिंग"CD"M() के साथ संगतता है।

वास्तव में, संयोजन अनुकूलक पता चलता है कि स्ट्रिंग संयोजन साहचर्य है, और पहले उदाहरण के लिए String.Concat(M(), "AB") उत्पन्न करता है, कि भले ही छोड़ दिया संबद्धता का उल्लंघन करती है।

तुम भी ऐसा कर सकते हैं:

string s = (M() + "E") + ("F" + M())); 

और हम अभी भी String.Concat(M(), "EF", M()) जेनरेट करना होगा।

दूसरा दिलचस्प बिंदु यह है कि शून्य और खाली तारों को अनुकूलित किया जाता है। तो अगर आप ऐसा करते हैं: क्या इस बारे में:

string s = (M() + "") + (null + M()); 

आप String.Concat(M(), M())

एक दिलचस्प सवाल तो उठाया है मिल जाएगा?

string s = M() + null; 

हम उस

string s = M(); 

करने के लिए नीचे अनुकूलन कर सकते हैं नहीं है, क्योंकि M() अशक्त लौट सकता है, लेकिन String.Concat(M(), null) कोई रिक्त स्ट्रिंग वापसी होगी अगर M() रिटर्न शून्य। तो क्या हम करते हैं बजाय

string s = M() + null; 

इस प्रकार का प्रदर्शन है कि स्ट्रिंग संयोजन वास्तव में सब पर String.Concat फोन की जरूरत नहीं

string s = M() ?? ""; 

को कम है।

इस विषय पर आगे पढ़ने के लिए,

Why is String.Concat not optimized to StringBuilder.Append?

+0

मुझे लगता है कि वहां कुछ त्रुटियां फिसल गई होंगी। निश्चित रूप से, '("सी" + "डी") + एम())' स्ट्रिंग उत्पन्न करता है। कॉनकैट ("सीडी", एम()) ', नहीं 'स्ट्रिंग। कॉनकैट (एम()," एबी ")'। और आगे नीचे, '(एम() + "ई") + (शून्य + एम())' स्ट्रिंग। कॉनकैट (एम(), "ई", एम()) उत्पन्न करना चाहिए, 'स्ट्रिंग नहीं। कॉनकैट (एम(), एम()) '। शुरुआती अनुच्छेद के लिए – hammar

+21

+1। :) इस तरह के जवाब हमेशा स्टैक ओवरफ़्लो के बारे में मुझे आश्चर्यचकित करते हैं। – brichins