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


115

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

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

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

String result = "1" + "2";

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


स्ट्रिंग्स को केवल तब ही इंटर्न किया जाता है यदि आप स्पष्ट रूप से स्ट्रिंग कहते हैं। स्टर्न।
जो व्हाइट

7
@ जोवेइट: वे हैं?
इगोर कोरकोव

13
काफी नहीं। सभी स्ट्रिंग शाब्दिक स्वचालित रूप से नजरबंद हैं। स्ट्रिंग ऑपरेशन के परिणाम नहीं हैं।
स्टीफन पॉल नैक

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

+1। उस शैली में एक स्ट्रिंग कैटेनेशन को कोड करने की आवश्यकता के वास्तविक जीवन के उदाहरण के लिए, msdn.microsoft.com/en-us/library/… के उदाहरण अनुभाग में एक है जो संकलक इसे अनुकूलित करने में असमर्थ थे, तो यह संभव नहीं होगा। एक एकल स्थिरांक के कारण, मानों पर बाधाओं को विशेषता मापदंडों को सौंपा गया है।
ClickRick

जवाबों:


161

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

यदि आप इसे एक विधि में करते हैं:

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

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

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

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);
}

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

ध्यान रखें कि रनटाइम के दौरान और अनुकूलन हो सकते हैं। मैं सिर्फ वही चला रहा हूं जो IL प्रोड्यूस करता है।

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

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();
    }
}

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

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

लेकिन (आश्चर्यजनक रूप से), संकलक द्वारा एक ही बहु-स्ट्रिंग संयोजन में कई लगातार संयोजन किए जाते हैं। उदाहरण के लिए, यह प्रोग्राम केवल 12 स्ट्रिंग इंस्टेंसेस भी तैयार करता है! ऐसा इसलिए है क्योंकि " भले ही आप एक बयान में कई + ऑपरेटरों का उपयोग करते हैं, स्ट्रिंग सामग्री केवल एक बार कॉपी की जाती है। "

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

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

यहां तक ​​कि एक स्ट्रिंग में परिणाम। मैं बस इसे LinqPad के माध्यम से अपने आप को दोगुना करने के लिए दौड़ा।
क्रिस शिन

1
@ सर्वे - टिप्पणी से लगता है कि अद्यतन किया गया है। जब आप किसी टिप्पणी को बदलते हैं तो उसे परिवर्तित नहीं होने के रूप में चिह्नित किया जाता है।
सिक्योरिटी हाउंड

1
एक मामला जो पूर्णता पर विचार करने के लिए अच्छा होगा, एक लूप में समाप्‍त हो रहा है। उदाहरण के लिए निम्नलिखित कोड कितनी स्ट्रिंग ऑब्जेक्ट आवंटित करता है:string s = ""; for (int i = 0; i < n; i++) s += "a";
जोरेन

1
मैं LINQPad ( linqpad.net ) या रिफ्लेक्टर ( रिफ्लेक्टर . net ) का उपयोग करता हूं । पूर्व आपको कोड के अनियंत्रित स्निपेट के आईएल को दिखाता है, बाद वाले डिकम्पाइलस आईएल में असेंबल करते हैं और उस आईएल के बराबर सी # उत्पन्न कर सकते हैं। ILDASM ( msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.80).aspx ) नामक एक बिल्ट-इन टूल भी है। आईएल को समझना एक मुश्किल काम है- कोडरटर को देखें-raymondlewallen/2005/ ०२ / ० 02 /…
१६:४५ पर क्रिस शिन

85

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

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

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 s = M() ?? "";

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

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

क्यों String.Concat StringBuilder.Append के लिए अनुकूलित नहीं है?


मुझे लगता है कि कुछ त्रुटियां हो सकती हैं। निश्चित रूप से, ("C" + "D") + M())उत्पन्न करता है String.Concat("CD", M()), नहीं String.Concat(M(), "AB")। और आगे नीचे, (M() + "E") + (null + M())उत्पन्न करना चाहिए String.Concat(M(), "E", M()), नहीं String.Concat(M(), M())
हमार

21
प्रारंभिक पैराग्राफ के लिए +1। :) इस तरह के उत्तर हमेशा स्टैक ओवरफ्लो के बारे में मुझे आश्चर्यचकित करते हैं।
ब्रिचिन

23

मुझे MSDN पर जवाब मिला। एक।

कैसे करें: कॉनटेनटेट मल्टीपल स्ट्रिंग्स (C # प्रोग्रामिंग गाइड)

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


22

बस एक ठो। C # संकलक स्ट्रिंग स्थिरांक को मोड़ देगा और इसलिए यह अनिवार्य रूप से नीचे संकलन करता है

String result = "1234";

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

1
सामान्य तौर पर लेकिन निरंतर तह अनावश्यक मध्यवर्ती कदमों को हटा देगा
जारेडपर

13

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


3
यह कम से कम Microsoft के C # संकलक के लिए VS 2008 और 2010 के व्यवहार का दस्तावेज है (देखें @ डेविड-स्ट्रैटन का उत्तर)। उस ने कहा, आप सही हैं- जहां तक ​​मैं एक त्वरित गड़बड़ी से बता सकता हूं, सी # कल्पना यह निर्दिष्ट नहीं करती है और शायद इसे कार्यान्वयन विवरण माना जाना चाहिए।
क्रिस शिन

13

एक, चूंकि वे स्थिर हैं, इसलिए कंपाइलर संकलन समय पर इसे एक स्ट्रिंग में ऑप्टिमाइज़ कर पाएंगे।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.