سؤال

ما هي أطول سلسلة يمكن إنشاؤها في .NET؟المستندات الخاصة بـ String الفصل صامت بشأن هذا السؤال بقدر ما أستطيع أن أرى، لذا قد تتطلب الإجابة الرسمية بعض المعرفة بالأمور الداخلية.هل سيتغير الحد الأقصى على نظام 64 بت؟

[يُطلب هذا من باب الفضول أكثر من الاستخدام العملي - لا أنوي إنشاء أي كود يستخدم سلاسل ضخمة!]

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

المحلول

قد يكون الحد النظري 2,147,483,647، لكن الحد العملي ليس قريبًا من ذلك.نظرًا لعدم وجود كائن واحد في برنامج .NET قد يزيد حجمه عن 2 غيغابايت وأن نوع السلسلة يستخدم Unicode (2 بايت لكل حرف)، فإن أفضل ما يمكنك فعله هو 1,073,741,823، ولكن من غير المرجح أن تتمكن من تخصيص ذلك على الإطلاق آلة 32 بت.

هذه واحدة من تلك المواقف التي "إذا كان عليك أن تسأل، فمن المحتمل أنك تفعل شيئًا خاطئًا."

نصائح أخرى

واستنادًا إلى تجربتي العلمية والدقيقة للغاية، فإن الرقم يصل إلى 1,000,000,000 حرف على جهازي.(ما زلت أقوم بتشغيل الكود أدناه للحصول على دقة أفضل).

تحديث:وبعد بضع ساعات، لقد استسلمت.النتائج النهائية:يمكن أن يصل حجمه إلى أكثر من 100.000.000 حرف، على الفور System.OutOfMemoryException في 1،000،000،000 حرف.

using System;
using System.Collections.Generic;

public class MyClass
{
    public static void Main()
    {
        int i = 100000000;
        try
        {
            for (i = i; i <= int.MaxValue; i += 5000)
            {
                string value = new string('x', i);
                //WL(i);
            }
        }
        catch (Exception exc)
        {
            WL(i);
            WL(exc);
        }
        WL(i);
        RL();
    }

    #region Helper methods

    private static void WL(object text, params object[] args)
    {
        Console.WriteLine(text.ToString(), args);   
    }

    private static void RL()
    {
        Console.ReadLine(); 
    }

    private static void Break() 
    {
        System.Diagnostics.Debugger.Break();
    }

    #endregion
}

منذ Length ممتلكات System.String هو Int32, ، أعتقد أن الحد الأقصى للطول سيكون 2,147,483,647 حرفًا (بحد أقصى Int32 مقاس).إذا سمحت لفترة أطول فلن تتمكن من التحقق من الطول لأن ذلك قد يفشل.

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

ال StringBuilder غالبًا ما يكون الفصل بديلاً سهلاً.النظر في واحدة من الطبقات القائمة على الدفق خاصة إذا كانت بياناتك قادمة من ملف.

المشكلة مع s += "stuff" هو أنه يجب عليه تخصيص منطقة جديدة تمامًا للاحتفاظ بالبيانات ثم نسخ كافة البيانات القديمة إليها بالإضافة إلى العناصر الجديدة - كل حلقة تكرار.لذلك، إضافة خمسة بايت إلى 1،000،000 مع s += "stuff" مكلفة للغاية.إذا كان ما تريده هو كتابة خمسة بايت فقط حتى النهاية والمضي قدمًا في برنامجك، فيجب عليك اختيار فئة تترك مجالًا للنمو:

StringBuilder sb = new StringBuilder(5000);
for (; ; )
    {
        sb.Append("stuff");
    }

StringBuilder سوف النمو التلقائي عن طريق المضاعفة عندما يتم ضرب الحد.لذا، ستلاحظ صعوبة النمو مرة واحدة في البداية، مرة عند 5000 بايت، ومرة ​​أخرى عند 10000 بايت، ومرة ​​أخرى عند 20000 بايت.سيؤدي إلحاق السلاسل إلى تحمل الألم في كل تكرار للحلقة.

الحد الأقصى لطول السلسلة على الجهاز الخاص بي يكون 1,073,741,791.

كما ترى، السلاسل النصية ليست محدودة بعدد صحيح كما هو شائع.

وبغض النظر عن قيود الذاكرة، لا يمكن أن تحتوي السلاسل على أكثر من 230 (1,073,741,824) ، حيث يتم فرض حد يبلغ 2 جيجابايت بواسطة Microsoft CLR (وقت تشغيل اللغة العامة).33 أكثر مما يسمح به جهاز الكمبيوتر الخاص بي.

الآن، إليك شيء يمكنك تجربته بنفسك.

قم بإنشاء تطبيق وحدة تحكم C# جديد في Visual Studio ثم قم بنسخ/لصق الطريقة الرئيسية هنا:

static void Main(string[] args)
{
    Console.WriteLine("String test, by Nicholas John Joseph Taylor");

    Console.WriteLine("\nTheoretically, C# should support a string of int.MaxValue, but we run out of memory before then.");

    Console.WriteLine("\nThis is a quickish test to narrow down results to find the max supported length of a string.");

    Console.WriteLine("\nThe test starts ...now:\n");

    int Length = 0;

    string s = "";

    int Increment = 1000000000; // We know that s string with the length of 1000000000 causes an out of memory exception.

    LoopPoint:

    // Make a string appendage the length of the value of Increment

    StringBuilder StringAppendage = new StringBuilder();

    for (int CharacterPosition = 0; CharacterPosition < Increment; CharacterPosition++)
    {
        StringAppendage.Append("0");

    }

    // Repeatedly append string appendage until an out of memory exception is thrown.

    try
    {
        if (Increment > 0)
            while (Length < int.MaxValue)
            {
                Length += Increment;

                s += StringAppendage.ToString(); // Append string appendage the length of the value of Increment

                Console.WriteLine("s.Length = " + s.Length + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));

            }

    }
    catch (OutOfMemoryException ex) // Note: Any other exception will crash the program.
    {
        Console.WriteLine("\n" + ex.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Length -= Increment;

        Increment /= 10;

        Console.WriteLine("After decimation, the value of Increment is " + Increment + ".");

    }
    catch (Exception ex2)
    {
        Console.WriteLine("\n" + ex2.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Console.WriteLine("Press a key to continue...");

        Console.ReadKey();

    }

    if (Increment > 0)
    {
        goto LoopPoint;

    }

    Console.WriteLine("Test complete.");

    Console.WriteLine("\nThe max length of a string is " + s.Length + ".");

    Console.WriteLine("\nPress any key to continue.");

    Console.ReadKey();

}

وكانت نتائجي كالتالي:

اختبار السلسلة لنيكولاس جون جوزيف تايلور

من الناحية النظرية ، يجب أن يدعم C# سلسلة من int.maxvalue ، لكننا نفد الذاكرة قبل ذلك.

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

يبدأ الاختبار...الآن:

الطول = 1000000000 في 08/05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد الانتهاء ، قيمة الزيادة هي 100000000.

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد الانتهاء ، قيمة الزيادة هي 10000000.S.Length = 1010000000 في 08/05/2019 12:06 S.Length = 1020000000 في 08/05/2019 12:06 S.Length = 1030000000 في 08/05/2019 12:06 S.Length = 1040000000 في 08/ 05/2019 12:06 S.Length = 1050000000 at 08/05/2019 12:06 S.Length = 1060000000 at 08/05/2019 12:06 S.Length = 1070000000 at 08/05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد العشرية تكون قيمة الزيادة 1000000.S.Length = 1071000000 في 08/05/2019 12:06 S.Length = 1072000000 في 08/05/2019 12:06 S.Length = 1073000000 at 08/05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد العشرية تكون قيمة الزيادة 100000.S.Length = 1073100000 في 08/05/2019 12:06 S.Length = 1073200000 في 08/05/2019 12:06 S.Length = 1073300000 في 08/05/2019 12:06 S.Length = 1073400000 في 08/ 05/2019 12:06 S.Length = 1073500000 at 08/05/2019 12:06 S.Length = 1073600000 at 08/05/2019 12:06 S.Length = 1073700000 at 08/05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد العلامة العشرية تكون قيمة الزيادة 10000.S.Length = 1073710000 في 08/05/2019 12:06 S.Length = 1073720000 في 08/05/2019 12:06 S.Length = 1073730000 في 08/05/2019 12:06 05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد العشرية تكون قيمة الزيادة هي 1000.الطول = 1073741000 في 08/05/2019 12:06

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:06.بعد العلامة العشرية، قيمة الزيادة هي 100.S.Length = 1073741100 في 08/05/2019 12:06 S.Length = 1073741200 في 08/05/2019 12:06 S.Length = 1073741300 في 08/05/2019 12:07 05/2019 12:07 S.Length = 1073741500 at 08/05/2019 12:07 S.Length = 1073741600 at 08/05/2019 12:07 S.Length = 1073741700 at 08/05/2019 12:07

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:07.بعد العلامة العشرية، قيمة الزيادة هي 10.S.Length = 1073741710 في 08/05/2019 12:07 S.Length = 1073741720 في 08/05/2019 12:07 S.Length = 1073741730 في 08/05/2019 12:07 S.Length = 1073741740 في 08/ 05/2019 12:07 S.Length = 1073741750 at 08/05/2019 12:07 S.Length = 1073741760 at 08/05/2019 12:07 S.Length = 1073741770 at 08/05/2019 12:07 S. الطول = 1073741780 في 08/05/2019 12:07 S.Length = 1073741790 في 08/05/2019 12:07

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:07.بعد العلامة العشرية، قيمة الزيادة هي 1.الطول = 1073741791 في 08/05/2019 12:07

تم طرح استثناء من النوع 'System.OutOfMemoryException'.في 08/05/2019 12:07.بعد العلامة العشرية، قيمة الزيادة هي 0.اختبار كامل.

الحد الأقصى لطول السلسلة هو 1073741791.

اضغط على أى زر للاستمرار.

الحد الأقصى لطول السلسلة على جهازي هو 1073741791.

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

سيكون من المثير للاهتمام معرفة ما إذا كان الأشخاص يحصلون على نفس النتائج أو نتائج مختلفة.

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

static void Main(string[] args)
{
    string s = "hello world";
    for(;;)
    {
        s = s + s.Substring(0, s.Length/10);
        Console.WriteLine(s.Length);
    }
}

12
13
14
15
16
17
18
...
158905664
174796230
192275853
211503438

منذ String.Length هو عدد صحيح (وهذا هو الاسم المستعار لـ Int32) ، يقتصر حجمها على Int32.MaxValue أحرف يونيكود.؛-)

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