سؤال

ما هي الطريقة الأكثر فعالية لسلسلة السلاسل ؟

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

المحلول

على StringBuilder.Append() الطريقة هي أفضل بكثير من استخدام + المشغل.ولكني وجدت أنه عند تنفيذ 1000 تسلسالت أو أقل ، String.Join() هو أكثر كفاءة من StringBuilder.

StringBuilder sb = new StringBuilder();
sb.Append(someString);

المشكلة الوحيدة مع String.Join هو أن لديك لسلسلة السلاسل مشترك محدد.(تحرير:) كما @ryanversaw أشار يمكنك جعل محدد السلسلة.فارغة.

string key = String.Join("_", new String[] 
{ "Customers_Contacts", customerID, database, SessionID });

نصائح أخرى

ريكو مارياني, ، .صافي أداء المعلم ، مقال في هذا الموضوع بالذات.انها ليست بسيطة كما قد يظن المرء.الأساسية النصيحة هي:

إذا كان النمط الخاص بك تبدو مثل:

x = f1(...) + f2(...) + f3(...) + f4(...)

هذا هو واحد concat و هو رشيق, بـ stringbuilder ربما لن يساعد.

إذا كان النمط الخاص بك تبدو مثل:

if (...) x += f1(...)
if (...) x += f2(...)
if (...) x += f3(...)
if (...) x += f4(...)

ثم ربما كنت ترغب بـ stringbuilder.

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

هناك 6 أنواع من سلسلة تسلسالت:

  1. باستخدام زائد (+) رمزا.
  2. باستخدام string.Concat().
  3. باستخدام string.Join().
  4. باستخدام string.Format().
  5. باستخدام string.Append().
  6. باستخدام StringBuilder.

في تجربة ، وقد ثبت أن string.Concat() هو أفضل طريقة لمعالجة إذا كانت الكلمات هي أقل من 1000(تقريبا) و إن كانت الكلمات أكثر من 1000 ثم StringBuilder ينبغي أن تستخدم.

للحصول على مزيد من المعلومات ، يرجى مراجعة هذا الموقع.

السلسلة.الانضمام إلى() vs السلسلة.Concat()

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

من Chinh أفعل بـ stringbuilder ليست دائما أسرع:

قواعد الإبهام

  • عندما وصل ثلاثة ديناميكية سلسلة القيم أو أقل ، استخدام التقليدية سلسلة سلسلة.

  • عندما وصل أكثر من ثلاثة ديناميكية سلسلة القيم ، واستخدام بـ stringbuilder.

  • عند بناء كبير سلسلة من عدة سلسلة حرفية استخدام إما @ سلسلة حرفية أو مضمنة + المشغل.

معظم الوقت بـ stringbuilder هو أفضل رهان ، ولكن هناك حالات كما هو مبين في هذا المنصب أنه على الأقل يجب أن نفكر في كل حالة.

إذا كنت تعمل في حلقة بـ stringbuilder ربما هو الطريق للذهاب ، فإنه يوفر لك النفقات العامة من إنشاء سلاسل جديدة بانتظام.في التعليمات البرمجية التي سوف تعمل فقط مرة واحدة ، على الرغم من السلسلة.Concat هو على الارجح ما يرام.

ومع ذلك ، ريكو مارياني (.صافي الأمثل المعلم) تتكون مسابقة الذي ذكر في النهاية أنه في معظم الحالات ، يوصي السلسلة.تنسيق.

هنا هو أسرع طريقة لقد تطورت أكثر من عقد بلدي نطاق واسع البرمجة اللغوية العصبية التطبيق.لدي الاختلافات IEnumerable<T> وغيرها من أنواع المدخلات ، و دون فواصل من أنواع مختلفة (Char, String), ولكن أنا هنا تظهر قضية وصل جميع السلاسل في صفيف في سلسلة واحدة مع أي فاصل.أحدث نسخة هنا هو تطوير وحدة اختبار على C# 7 و .صافي 4.7.

هناك نوعان من مفاتيح العالي الأداء ؛ الأولى هي مرحلة ما قبل حساب الدقيق الحجم الإجمالي المطلوب.هذه الخطوة هي تافهة عند إدخال مجموعة كما هو موضح هنا.التعامل مع IEnumerable<T> بدلا من ذلك, ومن الجدير أول تجمع الخيوط الى مؤقتة مجموعة الحوسبة أن إجمالي (المصفوفة هو مطلوب لتجنب الاتصال ToString() أكثر من مرة واحدة لكل عنصر منذ تقنيا ، نظرا لإمكانية من الآثار الجانبية ، وبذلك يمكن تغيير المتوقع دلالات من سلسلة الانضمام إلى' عملية).

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

...ملاحظة أن هذا هو فقط السائبة-سلسلة الحل في هذه الصفحة التي يتجنب تماما وهو جولة إضافية من التخصيص والنسخ قبل String منشئ.

رمز كاملة:

/// <summary>
/// Concatenate the strings in 'rg', none of which may be null, into a single String.
/// </summary>
public static unsafe String StringJoin(this String[] rg)
{
    int i;
    if (rg == null || (i = rg.Length) == 0)
        return String.Empty;

    if (i == 1)
        return rg[0];

    String s, t;
    int cch = 0;
    do
        cch += rg[--i].Length;
    while (i > 0);
    if (cch == 0)
        return String.Empty;

    i = rg.Length;
    fixed (Char* _p = (s = new String(default(Char), cch)))
    {
        Char* pDst = _p + cch;
        do
            if ((t = rg[--i]).Length > 0)
                fixed (Char* pSrc = t)
                    memcpy(pDst -= t.Length, pSrc, (UIntPtr)(t.Length << 1));
        while (pDst > _p);
    }
    return s;
}

[DllImport("MSVCR120_CLR0400", CallingConvention = CallingConvention.Cdecl)]
static extern unsafe void* memcpy(void* dest, void* src, UIntPtr cb);

أود أن أذكر أن هذا الرمز قد تعديل طفيف عن ما في نفسي.في الأصل أنا الاتصال cpblk IL التعليمات من C# القيام الفعلي النسخ.البساطة و قابلية في المدونة هنا ، أنا محل أن مع P/الاحتجاج memcpy بدلا من ذلك, كما ترون.على أعلى مستوى من الأداء على x64 (ولكن ربما لا x86) قد ترغب في استخدام cpblk الطريقة بدلا من ذلك.

من هذا المقالة MSDN:

هناك بعض النفقات المرتبطة وخلق بـ stringbuilder كائن ، سواء في الوقت والذاكرة.على جهاز مع الذاكرة السريعة ، يصبح بـ stringbuilder من المفيد إذا كنت تفعل خمسة عمليات.وكقاعدة عامة من الإبهام, أنا يقول 10 أو أكثر من سلسلة عمليات هو تبرير النفقات العامة على أي آلة ، حتى أبطأ واحد.

لذلك إذا كنت تثق MSDN تذهب مع بـ stringbuilder إذا كان عليك أن تفعل أكثر من 10 سلاسل العمليات/تسلسالت - وإلا بسيطة سلسلة concat مع '+' على ما يرام.

إضافة إلى إجابات أخرى ، يرجى أن نضع في اعتبارنا أن بـ stringbuilder يمكن أن يقال أولية مقدار الذاكرة لتخصيص.

على القدرات المعلمة يحدد الحد الأقصى لعدد الأحرف التي يمكن تخزينها في الذاكرة المخصصة من قبل المثيل الحالي.قيمته المخصصة القدرات مكان الإقامة.إذا كان عدد الأحرف التي يتم تخزينها في هذه الحالة يتجاوز هذا القدرات القيمة بـ stringbuilder كائن يخصص ذاكرة إضافية لتخزين لهم.

إذا القدرات هو صفر ، تنفيذ محددة الافتراضي القدرة المستخدمة.

مرارا وتكرارا إلى إلحاق بـ stringbuilder التي لم تكن قبل المخصصة يمكن أن يؤدي إلى الكثير من لا لزوم لها مخصصات فقط مثل مرارا وصل العادية السلاسل.

إذا كنت تعرف كم من الوقت النهائي السلسلة سوف تكون, يمكن مسلي حساب ذلك ، أو يمكن أن تجعل تكهنا حول قضية مشتركة (تخصيص الكثير ليس بالضرورة أمرا سيئا) ، وينبغي تقديم هذه المعلومات إلى منشئ أو القدرات مكان الإقامة. خاصة عند تشغيل اختبارات الأداء مقارنة بـ stringbuilder مع الأساليب الأخرى مثل السلسلة.Concat التي تفعل الشيء نفسه داخليا.أي اختبار تراه على الانترنت التي لا تشمل بـ stringbuilder قبل التخصيص في مقارنات خاطئة.

إذا كنت لا يمكن أن تجعل أي نوع من التخمين حول حجم, ربما كنت أكتب وظيفة الأداة التي يجب أن يكون لديك الخاصة الاختياري حجة للسيطرة على ما قبل التخصيص.

ومن المهم أيضا أن نشير بها التي يجب عليك استخدام + مشغل إذا وصل سلسلة حرفية.

عند لسلسلة سلسلة حرفية أو سلسلة الثوابت باستخدام مشغل + المحول البرمجي بإنشاء سلسلة واحدة.لا وقت تشغيل سلسلة يحدث.

كيفية:سلسلة سلاسل متعددة (C# البرمجة دليل)

التالية قد يكون أحد أكثر بديل حل لسلسلة سلاسل متعددة.

String str1 = "sometext";
string str2 = "some other text";

string afterConcate = $"{str1}{str2}";

سلسلة الاستيفاء

الأكثر فعالية هو استخدام بـ stringbuilder مثل:

StringBuilder sb = new StringBuilder();
sb.Append("string1");
sb.Append("string2");
...etc...
String strResult = sb.ToString();

@jonezy:السلسلة.Concat على ما يرام إذا كان لديك اثنين من الأشياء الصغيرة.ولكن إذا كنت وصل ميغا بايت من البيانات, البرنامج الخاص بك من المرجح أن الخزان.

جرب هذا 2 قطعة من التعليمات البرمجية وسوف تجد الحل.

 static void Main(string[] args)
    {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < 10000000; i++)
        {
            s.Append( i.ToString());
        }
        Console.Write("End");
        Console.Read();
    }

مقابل

static void Main(string[] args)
    {
        string s = "";
        for (int i = 0; i < 10000000; i++)
        {
            s += i.ToString();
        }
        Console.Write("End");
        Console.Read();
    }

سوف تجد أن 1 رمز ستنتهي حقا سريعة و الذاكرة سوف يكون في مبلغ جيد.

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

الهتافات.

النظام.سلسلة غير قابل للتغيير.عندما نقوم بتعديل قيمة متغير سلسلة ثم جديد يتم تخصيص الذاكرة إلى قيمة جديدة السابقة تخصيص الذاكرة صدر.النظام.بـ stringbuilder وقد تم تصميم مفهوم قابلة للتغيير السلسلة حيث مجموعة متنوعة من العمليات يمكن القيام بها دون تخصيص ذاكرة منفصلة موقع تعديل السلسلة.

حل آخر:

داخل الحلقة ، استخدم قائمة بدلا من السلسلة.

List<string> lst= new List<string>();

for(int i=0; i<100000; i++){
    ...........
    lst.Add(...);
}
return String.Join("", lst.ToArray());;

هو جدا سريع جدا.

أنها حقا يتوقف على استخدامك.مفصل القياسي بين السلسلة.Join, سلسلة,Concat السلسلة.شكل يمكن العثور عليها هنا: السلسلة.الصيغة غير مناسبة مكثفة تسجيل

(وهذا هو في الواقع نفس الجواب أعطى هذا السؤال)

فقط اثنين من سلاسل, أنت بالتأكيد لا تريد استخدام بـ stringbuilder.هناك بعض عتبة أعلاه التي بـ stringbuilder النفقات العامة أقل من النفقات العامة تخصيص سلاسل متعددة.

لذا لأكثر من 2-3 سلاسل, استخدام DannySmurf كود.وإلا مجرد استخدام + المشغل.

فإنه يعتمد على المدونة.بـ stringbuilder هو أكثر كفاءة عموما, ولكن إذا كنت فقط وصل عدد قليل من السلاسل و تفعل كل شيء في سطر واحد, تحسينات رمز من المرجح أن تأخذ الرعاية من ذلك بالنسبة لك.من المهم أن نفكر كيف تبدو التعليمة البرمجية أيضا:أكبر مجموعات بـ stringbuilder سوف تجعل من الأسهل قراءة الصغيرة منها بـ stringbuilder فقط إضافة فوضى لا داعي لها.

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