ما هو استخدام النظام.السلسلة.نسخة في .الشبكة ؟

StackOverflow https://stackoverflow.com/questions/520895

سؤال

أخشى أن هذا هو سؤال سخيف, لكن يجب أن يكون في عداد المفقودين شيء.

لماذا قد ترغب في استخدام السلسلة.نسخ(سلسلة)?

الوثائق تقول الطريقة

إنشاء مثيل جديد من السلسلة نفس قيمة السلسلة المحددة.

منذ السلاسل هي ثابتة في .صافي انا غير متأكد ما هي الفائدة من استخدام هذا الأسلوب ، كما أنني أعتقد أن

 string copy = String.Copy(otherString);

سيكون من الناحية العملية يبدو أن تحقق نفس النتيجة

 string copy = otherString;

ذلك فيما عدا ما الداخلي مسك الدفاتر التي يجري حقيقة أن نسخة ليست ReferenceEquals إلى otherString لا توجد الاختلافات الملحوظة - سلسلة كونه غير قابل للتغيير فئة الذين المساواة على أساس القيمة ، وليس الهوية.(شكرا ل @أندرو الأرنب بالنسبة مشيرا إلى أن بلدي الأصلي الصيغة لم يكن دقيقا بما فيه الكفاية للإشارة إلى أن أدركت أنه كان هناك فرق بين Copyجي وليس ولكنها تشعر بالقلق إزاء نقص مفيدة الفرق.)

بالطبع عندما مرت null الحجة نسخ يلقي ArgumentNullException, و "جديدة سبيل المثال" قد تستهلك المزيد من الذاكرة.هذا الأخير لا يبدو فائدة, وأنا لست متأكدا من أن null check المكافأة كافية لتبرير كل نسخ الأسلوب.

شكرا

هل كانت مفيدة؟

المحلول

ومع String.Copy كنت تخصيص الواقع ذاكرة جديدة ونسخ الأحرف من سلسلة واحدة إلى أخرى. تحصل على مثيل جديد تماما بدلا من وجود كل المتغيرات يجري نفس مثيل. قد يهم هذا إذا كنت تستخدم السلسلة مع التعليمات البرمجية غير المدارة التي تتعامل مع مواقع الذاكرة مباشرة، ويمكن أن يتحور السلسلة.

نصائح أخرى

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 إشارة إلى أن له نفس محتويات ولكن وجوه مختلفة على كومة.


تحرير: هناك الكثير من الناس التي هي مستاء جدا من هذا الجواب لم OP سؤال.أعتقد أنني لم أجب على السؤال عن طريق تصحيح فرضية غير صحيحة في السؤال نفسه.هنا هو مماثل (إن لم يكن التبسيط) السؤال و الجواب أن نأمل توضيح وجهة نظري:

السؤال:

ولقد لوحظ أن سيارتي له بابين واحد على كل جانب من السيارة.وأعتقد أنه حقيقة أنه بغض النظر عن الباب الذي أنا أستخدم أنا في نهاية المطاف يجلس في مقعد السائق.ما هو الغرض من غيرها من الباب ؟

الجواب:

في الواقع هذا ليس صحيحا أنه إذا كنت تستخدم أي باب سوف ينتهي في مقعد السائق.إذا كنت تستخدم باب السائق سوف ينتهي في مقعد السائق و الراكب جنب الباب سوف ينتهي في مقعد الراكب.

الآن في هذا المثال يمكن القول بأن الجواب ليس جوابا على السؤال "ما هو الغرض من الجانب الراكب الباب؟".لكن بما أن السؤال كان كليا بناء على اعتقاد خاطئ كيف الأبواب عملت هل بالضرورة أن تفنيد فرضية سوف تسلط الضوء على الغرض من الباب الآخر قبل خصم ؟

وهنا قطعة واحدة من اللغز. فإنه لا يفسر لماذا كنت تريد أن تفعل ذلك، لكنها لا تساعد شرح الفرق الفنية.

إذا كنت دبوس سلسلة باستخدام الكلمة 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

بحث سريع من خلال BCL على .NET 4.0 يدل على أن string.Copy الطريقة تسمى في حوالي نصف دزينة من الأماكن.العادات تقع في نحو هذه الفئات:

  1. عن إمكانية التشغيل المتداخل مع وظائف الأم التي يمكن أن تلحق الضرر سلاسل مرت في لهم.إذا كنت لا يمكن أن تؤثر على P/استدعاء الإعلان لا يمكنك إصلاح الوظيفة التي دعا ، string.Copy هو أفضل خيار.

  2. في الحالات حيث السلسلة هو تعديل في المكان لأسباب تتعلق بالأداء.إذا كنت بحاجة إلى تحويل عدد قليل من الأحرف إلى أحرف صغيرة في يحتمل أن تكون سلسلة طويلة ، فإن الطريقة الوحيدة للقيام بذلك دون نسخ سلسلة مرتين وخلق إضافية القمامة هو التحور ذلك.

  3. في الأماكن التي لا يبدو ضروريا.فمن الممكن جدا أن بعض المبرمجين هم أكثر تستخدم Java أو C++ سلاسل و لا يدركون أن نسخ سلسلة في C# نادرا ما تكون مفيدة.

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 اتخاذ المزيد من ذاكرة الوصول العشوائي ثم b، كنقاط a إلى المخزن المؤقت من حجم 100 أن StringBuilder بإنشائه. (انظر في الداخل من طريقة StringBuilder.ToString())


وأعتقد StringBuilder يجعل من استخدام String.Copy() وكونها جزءا من صافي StringBuilderdoes إطار تغيير محتويات string. لذلك string ليس غير قابل للتغيير دائما.

وبالإضافة إلى ما قاله 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).

وليس متأكد من أن هذا هو فائدة الفرق، لأن هناك آليات أفضل لالتزامن (لا أعتقد تأمين سلاسل فكرة جيدة جدا).

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

وكشف صناعة السيارات في التغيير؟

وأنا لست متأكدا كيف سلسلة التي يجري تنفيذها في .NET، ولكن أعتقد أن جافا هي إشارة جيدة.

في جاوة، سلسلة جديدة (شارع) أيضا أن تفعل ما String.copy (شارع)؛ لا، تخصيص سلسلة جديدة مع نفس القيمة.

ويبدو عديم الفائدة ولكن من المفيد جدا في تحسين الذاكرة.

وسلسلة تحتوي على حرف [] مع تعويض وطول في التنفيذ. إذا كنت تفعل شيئا مثل فرعية، وانها لن تفعل نسخة الذاكرة ولكن العودة تقاسم نفس شار [] مثيل سلسلة جديدة. في كثير من الحالات، وهذا النمط يوفر الكثير من نسخ الذاكرة وتخصيصها. ومع ذلك، إذا كنت سلاسل فرعية قطعة صغيرة ضمن سلسلة كبيرة طويلة. فإنه لا يزال الرجوع إلى حرف كبير [] حتى سلسلة كبيرة الأصلية هي قادرة على أن تكون GC.

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

ويمكن أن تجبر الكائن سلسلة جديدة تحيله من تلقاء شار [] لمنع تسرب خفية الذاكرة / النفايات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top