سؤال

لقد قمت بإنشاء تطبيق اختبار للاختبار ، هو StringBuilder Copy Data إلى مثيل آخر وتنموه عندما يكون طوله أكثر من السعة الحالية والتحقق في ildasm.exe ولكن يبدو متطابقًا.

كيفية التحقق من StringBuilder سوف نسخ بياناتها إلى مثيل جديد وتنمية المخزن المؤقت حسب الحد المحدد؟

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

المحلول

إذا كنت ترغب في فحص كيفية تنفيذ StringBuilder ، فما عليك سوى إطلاق النار على العاكس والنظر إليه. تنفيذ StringBuilder.Append(string) على النحو التالي

public StringBuilder Append(string value)
{
   if (value != null)
   {
      string stringValue = this.m_StringValue;
      IntPtr currentThread = Thread.InternalGetCurrentThread();
      if (this.m_currentThread != currentThread)
      {
         stringValue = string.GetStringForStringBuilder(stringValue, stringValue.Capacity);
      }
      int length = stringValue.Length;
      int requiredLength = length + value.Length;
      if (this.NeedsAllocation(stringValue, requiredLength))
      {
         string newString = this.GetNewString(stringValue, requiredLength);
         newString.AppendInPlace(value, length);
         this.ReplaceString(currentThread, newString);
      }
      else
      {
         stringValue.AppendInPlace(value, length);
         this.ReplaceString(currentThread, stringValue);
      }
   }
   return this;
}

انظر إلى القسم مع NeedsAllocation, GetNewString وهكذا دواليك للعثور على ما تبحث عنه.

نصائح أخرى

تمثل السعة الذاكرة المتجاورة المخصصة لـ StringBuilder. يمكن أن تكون السعة> = طول السلسلة. عندما يتم إلحاق المزيد من البيانات بـ StringBuilder من السعة ، يزيد StringBuilder تلقائيًا من السعة. نظرًا لتجاوز السعة (تم ملء ذاكرة متجاورة ولا تتوفر غرفة عازلة مزيد من العزلة) ، يتم تخصيص مساحة مخزن مؤقت أكبر ويتم نسخ البيانات من الذاكرة الأصلية إلى هذه المنطقة الجديدة.

لا ينسخ البيانات إلى "مثيل" جديد ولكن إلى "موقع الذاكرة" الجديد. يبقى المثيل كما هو ولكن يشير إلى موقع الذاكرة الجديد.

تحرير FYI: السعة الافتراضية لـ StringBuilder إذا لم يتم تحديدها أثناء الإنشاء 16

إذا كنت تريد رؤية مواقع الذاكرة لـ StringBuilder ، فيمكنك تصحيح تطبيقاتك والتحقق من الذاكرة باستخدام Debug> Windows> الذاكرة. يمكنك في الواقع رؤية عنوان كل بايت مخزّن في StringBuilder عند تشغيل STMT.

إذا كنت بحاجة إلى الحصول على المواقع بشكل برمجي هذا الرابط قد تساعد.

لا نختبر حقًا أن StringBuilder يعمل ، لأنه يحدث ، ولكن من أجل التمتع الخاص بك ، يمكنك دائمًا كتابة اختبار الوحدة.

StringBuilder sb = new StringBuilder(10);
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
sb.Append("1234567890");
sb.Append("1234567890");
sb.Append("1234567890");
Console.WriteLine("Capacity = " + sb.Capacity + " Length = " + sb.Length 
      + " MaxCapacity = " + sb.MaxCapacity);
Assert.AreEqual("123456789012345678901234567890"
      , sb.ToString()); // NUnit assert.

مما لا يثير الدهشة ، يمر ، ويتم إعطاء الإخراج التالي.

    Capacity = 10 Length = 0 MaxCapacity = 2147483647
    Capacity = 40 Length = 30 MaxCapacity = 2147483647

إن الطريقة التي يزيد بها stringBuilder عازلة عند الحاجة هي شيء يتم الاعتناء به من خلال الكود الداخلي لـ StringBuilder ؛ لن يظهر في رمز IL لتطبيقك ؛ لا يمكن للمترجم معرفة حجم الأوتار الكبيرة التي سيحتوي عليها StringBuilder بطريقة معينة ، حيث يمكن أن يختلف ذلك من وقت لآخر.

ومع ذلك ، عندما يكون stringBuilder يفعل زيادة المخزن المؤقت ، لن يؤدي إلى مثيل جديد StringBuilder. قد يؤدي ذلك إلى نسخ التمثيل الداخلي للسلسلة التي يحتفظ بها إلى مثيل جديد (لا أعرف ما يكفي من الأعمال الداخلية للفئة ليقول بالضبط ما يحدث).

يمكنك استخدام Reflector لمعرفة كيفية عمل StringBuilder.

انظر الطريقة

StringBuilder Append(string value)

بالنسبة إلى .NET 3.5 المنطق هو: إذا لم يكن طول المخزن المؤقت كافيًا للسلسلة الجديدة ، فقم بإنشاء مخزن مؤقت جديد بطول يساوي الحد الأقصى (Oldsize * 2 ، المطلوب).

بمعنى آخر ، يحاول StringBuffer مضاعفة المخزن المؤقت ، وإذا لم يكن ذلك كافيًا ، فإن حجم المخزن المؤقت فقط بما يكفي لتناسب السلسلة الجديدة.

تتم إزالة الإشارة إلى المخزن المؤقت القديم ويتم استرداد المخزن المؤقت القديم مع مجموعة القمامة التالية.

 class Program
    {
        static void Main()
        {
            StringBuilder sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16

            for (int i = 0; i < 50; i++) 
                sb.Append(i + ",");

            Console.WriteLine(sb.Capacity); //256

            sb = new StringBuilder();
            Console.WriteLine(sb.Capacity); //16
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top