2009-02-06 11 views
50

मुझे डर है कि यह एक बहुत ही मूर्ख सवाल है, लेकिन मुझे कुछ याद आना चाहिए।.NET में System.String.Copy का उपयोग क्या है?

कोई String.Copy(string) का उपयोग क्यों करना चाह सकता है?

प्रलेखन विधि कहते हैं

एक निर्दिष्ट स्ट्रिंग के रूप में एक ही मूल्य साथ स्ट्रिंग का एक नया उदाहरण बनाता है।

के बाद से तार .NET में अडिग हैं, मुझे यकीन है कि क्या इस पद्धति का उपयोग के लाभ है, के रूप में मुझे लगता है कि चाहते हैं कि

string copy = String.Copy(otherString); 
होगा

सभी व्यावहारिक प्रयोजनों के लिए एक ही उपज के लिए प्रतीत नहीं कर रहा हूँ परिणाम के रूप में

string copy = otherString; 

यही है, जो कुछ भी आंतरिक बहीखाता कि क्या हो रहा है के लिए छोड़कर, और तथ्य यह है कि नकल otherString को ReferenceEquals नहीं है, वहाँ कोई नमूदार मतभेद हैं - स्ट्रिंग अपरिवर्तनीय वर्ग जा रहा है जिसका समानता मूल्य पर आधारित है, पहचान नहीं। (धन्यवाद उनका कहना है कि अपने मूल शब्दों सटीक रूप से पर्याप्त संकेत मिलता है कि मुझे एहसास हुआ Copy आईएनजी और नहीं के बीच एक अंतर था, लेकिन उपयोगी अंतर के कथित कमी के बारे में चिंतित था नहीं था के लिए हरे @Andrew करने के लिए।)

बेशक जब null तर्क पारित किया गया, तो प्रतिलिपि ArgumentNullException फेंकता है, और "नया उदाहरण" अधिक स्मृति का उपभोग कर सकता है। उत्तरार्द्ध शायद ही कभी एक लाभ की तरह लगता है, और मुझे यकीन नहीं है कि शून्य चेक एक पूरी प्रतिलिपि विधि वारंट करने के लिए एक बड़ा पर्याप्त बोनस है।

धन्यवाद।

+1

अच्छी तरह से, मूर्ख प्रश्नों में बहुत सारे वोट अप हैं, – TarunG

उत्तर

32

String.Copy के साथ आप वास्तव में नई मेमोरी आवंटित कर रहे हैं और वर्णों को एक स्ट्रिंग से दूसरी स्ट्रिंग में कॉपी कर रहे हैं; आप एक बिल्कुल उदाहरण के रूप में दोनों चर होने के विरोध में एक पूरी तरह से नया उदाहरण मिलता है। इससे कोई फर्क नहीं पड़ता कि आप स्ट्रिंग का उपयोग अप्रबंधित कोड के साथ करते हैं जो स्मृति स्थानों से सीधे संबंधित है और स्ट्रिंग को म्यूटेट कर सकता है।

+0

यह मेरा अनुमान था। यह नरक के रूप में अजीब होगा अगर आपके पूरे आवेदन में पाठ यादृच्छिक रूप से बदलना शुरू हो जाता है ... – Will

+2

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

+2

यदि आप एक अपरिवर्तनीय वस्तु को संशोधित करने का प्रयास करते हैं तो एक बग पैटर्न की तरह लगता है। –

19

String.Copy एक नया String वापस आती है और के रूप में

String copy = otherString; 

एक ही परिणाम नहीं करता है इस प्रयास करें:

using System; 

class Program 
{ 
    static void Main() 
    { 
     String test = "test"; 
     String test2 = test; 
     String test3 = String.Copy(test); 

     Console.WriteLine(Object.ReferenceEquals(test, test2)); 
     Console.WriteLine(Object.ReferenceEquals(test, test3)); 

     Console.ReadLine(); 
    } 
} 

जब आप test2 = test इन संदर्भों को एक ही String को इंगित निर्धारित किया है। Copy फ़ंक्शन एक नया String संदर्भ देता है जिसमें एक ही सामग्री है लेकिन ढेर पर एक अलग वस्तु के रूप में।


संपादित करें: लोगों कि बहुत नाराज़ ओपी के सवाल का जवाब नहीं था कर रहे हैं की एक बहुत कुछ कर रहे हैं। मेरा मानना ​​है कि मैंने प्रश्न में गलत आधार को सही करके प्रश्न का उत्तर दिया था। यहाँ एक अनुरूप (oversimplified नहीं है) सवाल-जवाब है कि उम्मीद है कि मेरी बात को वर्णन होगा:

प्रश्न:

मैंने देखा है मेरी कार दो दरवाजे, एक है कि कार के प्रत्येक पक्ष पर । मेरा मानना ​​है कि यह सच है कि मैं किस दरवाजे का उपयोग करता हूं, मैं ड्राइवर की सीट में बैठेगा। दूसरे दरवाजे का उद्देश्य क्या है?

उत्तर:

वास्तव में यह सच नहीं है कि अगर आप या तो दरवाजे का उपयोग आप ड्राइवर की सीट में खत्म हो जाएगा। यदि आप ड्राइवर के साइड दरवाजे का उपयोग करते हैं तो आप ड्राइवर की सीट में खत्म हो जाएंगे और यदि आप यात्री के साइड दरवाजे का उपयोग करते हैं तो आप यात्री की सीट में खत्म हो जाएंगे।

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

+0

सवाल यह नहीं था कि "यह क्या करता है" लेकिन "मैं इसका उपयोग क्यों करूं?" –

+0

मुझे लगता है कि बिंदु था:" इसका उपयोग करने के बजाय अपरिवर्तनीय जानकारी डुप्लिकेट करने का क्या उपयोग है? " – PhiLho

+0

संपूर्ण प्रश्न झूठी आधार पर आधारित था " स्ट्रिंग वन = स्ट्रिंग.कॉपी (दो); " और "स्ट्रिंग वन = दो;" बराबर बयान हैं। मैं बस यह इंगित कर रहा था कि पोस्टर गलत था। –

6
string a = "abc"; 
string b = String.Copy(a); 

Monitor.Enter(a); // not the same as Monitor.Enter(b); 

हालांकि

string c = "123"; 
string d = c; 
Monitor.Enter(c); // the same as Monitor.Enter(d); 

तरह से किसी को भी परवाह जाएगा के रूप में, मुझे लगता है कि पूर्णता के लिए नहीं है।


इसके अलावा

StringBuilder sb = new StringBuilder(100); 
sb.Append("abc"); 
string a = sb.ToString(); 
string b = String.Copy(a); 

मुझे लगता है कि a आकार 100 कि StringBuilder बनाया का बफर करने के लिए तो b अधिक रैम तक का समय लग, a अंक के रूप में होगा। (StringBuilder.ToString() विधि के अंदर को देखो)


मुझे लगता है कि StringBuilder .NET फ़्रेमवर्क StringBuilderstring की सामग्री को बदल नहीं करता है का हिस्सा होने String.Copy() के उपयोग और बनाता है। तो string हमेशा अपरिवर्तनीय नहीं है।

+0

स्ट्रिंगबिल्डर के लिए स्ट्रिंग को कभी भी संशोधित करना आवश्यक नहीं है।आंतरिक रूप से यह एक सूची का उपयोग कर सकता है जो आकार में कुशलता से बढ़ेगा, और फिर ToString विधि सूची की सामग्री से एक स्ट्रिंग आवंटित करेगी। –

0
string a = "test"; 
string b = a; 
//Object.ReferenceEquals(a,b) is true 
a += "more"; 
//Object.ReferenceEquals(a,b) is now false ! 

ऑटो-चेंज डिटेक्शन?

+3

नहीं, स्ट्रिंग में संलग्न करना स्ट्रिंग का एक नया उदाहरण बनाता है (क्योंकि तार अपरिवर्तनीय हैं)। "ए" जोड़ने के बाद एक और उदाहरण इंगित करेगा। – edgi

-1

मुझे यकीन नहीं है कि स्ट्रिंग को .NET में कैसे कार्यान्वित किया जा रहा है, लेकिन मुझे लगता है कि जावा एक अच्छा संदर्भ है।

जावा में, नया स्ट्रिंग (str) भी String.copy (str) करता है; करते हैं, एक ही मूल्य के साथ एक नया स्ट्रिंग आवंटित करें।

यह बेकार लगता है लेकिन यह स्मृति अनुकूलन में बहुत उपयोगी है।

स्ट्रिंग में एक char [] ऑफसेट और कार्यान्वयन में लंबाई शामिल है। यदि आप एक सबस्ट्रिंग की तरह कुछ करते हैं, तो यह स्मृति प्रतिलिपि नहीं करेगा, लेकिन एक नया स्ट्रिंग इंस्टेंस साझा करने वाला एक ही char [] को वापस कर देगा। कई मामलों में, यह पैटर्न बहुत सारी स्मृति प्रतिलिपि और आवंटन को बचाएगा। हालांकि, यदि आप एक लंबे बड़े स्ट्रिंग के भीतर एक छोटे टुकड़े को प्रतिस्थापित करते हैं। यह अभी भी बड़े char [] के संदर्भ में होगा, यहां तक ​​कि मूल बड़ी स्ट्रिंग भी जीसी होने में सक्षम है।

String longString = // read 1MB text from a text file 
String memoryLeak = largeString.substring(100,102); 
largeString=null; 
// memoryLeak will be sized 1MB in the memory 
String smaller = new String(largeString.substring(100,102)); 
// smaller will be only few bytes in the memory 

यह नया स्ट्रिंग ऑब्जेक्ट मजबूर कर सकते हैं आवंटित यह खुद चार [] को रोकने के लिए छिपा स्मृति रिसाव/अपशिष्ट है।

+0

यह नहीं है कि यह कैसे काम करता है। बस यह मानते हुए कि .NET का एक ही कार्यान्वयन है क्योंकि जावा सही नहीं है। उस पर, उत्तर के पास सवाल से कोई लेना देना नहीं है। जब आप .ububring (100, 102): लंबाई 102 के साथ एक नई स्ट्रिंग बनाई गई है जिसमें वर्ण 100 शामिल हैं ... 201 –

1

tvanfosson के अलावा क्या (मुझे नहीं लगता कि आप प्रबंधित प्रबंधित स्ट्रिंग द्वारा अप्रबंधित कोड से उपयोग किए गए बफर तक पहुंच सकते हैं ... मुझे पता है कि यह मुश्किल होगा, कम से कम), मुझे विश्वास है कि कोई अंतर हो सकता है यदि स्ट्रिंग का उपयोग मल्टीथ्रेडेड कार्यक्षमता के लिए लॉक करने के लिए ऑब्जेक्ट के रूप में किया जाता है।

उदाहरण के लिए ...

using System; 

public class Class1 
{ 
    string example1 = "example"; 
    string example2 = example1; 

    public void ExampleMethod1() 
    { 
     lock (example1) 
     { 
      Console.WriteLine("Locked example 1"); 
      //do stuff... 
     } 
    } 

    public void ExampleMethod2() 
    { 
     lock (example2) 
     { 
      Console.WriteLine("Locked example 2"); 
      //do stuff 
     } 
    } 
} 

मेरा मानना ​​है कि यदि दो उदाहरण तरीकों समानांतर में चलाए जा रहे हैं, वे एक ही वस्तु पर ताला लगा दिया जाएगा और इस प्रकार एक, जबकि अन्य इसके अंदर है पर अमल करने में सक्षम नहीं होगा लॉक ब्लॉक।

लेकिन अगर आप इसे इस के लिए बदल ...

using System; 

public class Class1 
{ 
    string example1 = "example"; 
    string example2 = string.Copy(example1); 

    public void ExampleMethod1() 
    { 
     lock (example1) 
     { 
      Console.WriteLine("Locked example 1"); 
      //do stuff... 
     } 
    } 

    public void ExampleMethod2() 
    { 
     lock (example2) 
     { 
      Console.WriteLine("Locked example 2"); 
      //do stuff 
     } 
    } 
} 

तो मेरा मानना ​​है कि वे केवल एक अन्य सूत्र एक ही विधि (यानी किसी भी धागे ExampleMethod1 को क्रियान्वित करने तक प्रत्येक पूरा करता लॉक कर दिया जाएगा क्रियान्वित करने के निष्पादन को अवरुद्ध कर देगा, लेकिन वे exampleMethod2 चलाने वाले धागे में हस्तक्षेप नहीं करेंगे)।

यह सुनिश्चित नहीं है कि यह उपयोगी अंतर है, क्योंकि सिंक्रनाइज़ेशन के लिए बेहतर तंत्र हैं (मुझे नहीं लगता कि लॉकिंग स्ट्रिंग्स एक बहुत अच्छा विचार है)।

13

यहां पहेली का एक टुकड़ा है। यह समझा नहीं जाता कि आप ऐसा क्यों करना चाहते हैं, लेकिन यह एक कार्यात्मक अंतर की व्याख्या करने में मदद करता है।

यदि आप fixed कीवर्ड का उपयोग कर स्ट्रिंग को पिन करते हैं, तो सामग्री उत्परिवर्तनीय होगी। मेरे सिर के ऊपर से, मैं ऐसी स्थिति के बारे में नहीं सोच सकता जिसमें आप ऐसा करना चाहते हैं, लेकिन यह संभव है।

string original = "Hello World"; 
string refCopy = original; 
string deepCopy = String.Copy(original); 

fixed(char* pStr = original) 
{ 
    *pStr = 'J'; 
} 

Console.WriteLine(original); 
Console.WriteLine(refCopy); 
Console.WriteLine(deepCopy); 

आउटपुट:

Jello World 
Jello World 
Hello World 
+0

वह, क्रिंग योग्य और भयानक है। उदाहरण के लिए +1। –

+0

शानदार जवाब। – Kalyan

5

.NET 4.0 के लिए बीसीएल के माध्यम से एक त्वरित खोज से पता चलता है कि string.Copy विधि के बारे में आधे दर्जन से अधिक स्थानों में कहा जाता है। उपयोगों के मोटे तौर पर इन श्रेणियों में आने:

  1. देशी कार्यों कि तार उन्हें में पारित नुकसान पहुंचा सकता है के साथ इंटरॉप लिए। यदि आप पी/Invoke घोषणा को प्रभावित नहीं कर सकते हैं और आप फंक्शन को ठीक नहीं कर सकते हैं, string.Copy सबसे अच्छा विकल्प है।

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

  3. उन जगहों पर जहां यह आवश्यक नहीं लगता है। यह काफी संभव है कि कुछ प्रोग्रामर जावा या सी ++ तारों के लिए अधिक उपयोग किए जाते हैं और यह नहीं पता कि सी # में एक स्ट्रिंग की प्रतिलिपि बनाना शायद ही उपयोगी है।

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