Este String.Format la fel de eficient ca StringBuilder

Să presupunem că am un stringbuilder în C# care face acest lucru:

StringBuilder sb = new StringBuilder();
string cat = "cat";
sb.Append("the ").Append(cat).(" in the hat");
string s = sb.ToString();

ar fi la fel de eficiente sau mai eficiente ca având:

string cat = "cat";
string s = String.Format("The {0} in the hat", cat);

Dacă da, de ce?

EDIT

După câteva răspunsuri interesante, mi-am dat seama că probabil ar fi fost un pic mai clar în ceea ce am cerut. Am fost't atât de mult pentru a cere, care a fost mai rapid la concatenarea unui șir de caractere, dar care este mai rapidă la injecting un șir de caractere într-un alt.

În ambele cazuri de mai sus, vreau să vă injectați unul sau mai multe siruri de caractere în mijlocul unui șablon predefinit string.

Ne pare rău pentru confuzie

Comentarii la întrebare (3)
Soluția

NOTĂ: Acest răspuns a fost scris atunci când .NET 2.0 a fost versiunea curentă. Acest lucru poate nu se mai aplică la versiunile ulterioare.

String.Format folosește un StringBuilder` pe plan intern:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }

    StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
    builder.AppendFormat(provider, format, args);
    return builder.ToString();
}

Codul de mai sus este un fragment din mscorlib, deci, întrebarea devine "este StringBuilder.Append () mai repede decâtStringBuilder.AppendFormat()`"?

Fără benchmarking-am'd spune, probabil, ca exemplu de cod de mai sus ar rula mult mai rapid folosind .Append(). Dar's-o ghicească, să încerce benchmarking și/sau profilare cele două pentru a obține o comparație corectă.

Acest tip, Jerry Dixon, a făcut unele benchmarking:

Actualizat:

Din pacate link-ul de mai sus a murit. Cu toate acestea, acolo's încă o copie de pe Drumul de intoarcere Masina:

La sfârșitul zilei totul depinde de dumneavoastră dacă șirul de formatare este de gând să fie numit în mod repetat, de exemplu,'re face unele grave de procesare de text de peste 100 de's de megabytes de text, sau dacă-l's fiind numit atunci când un utilizator face clic pe un buton de acum și din nou. Dacă nu're face un lot mare de prelucrare de locuri de muncă I'd stick cu Coarde.Format, sida codul de lizibilitate. Dacă suspectați o perf strangulare apoi lipi un profiler privind codul dvs. și a vedea în cazul în care este într-adevăr este.

Comentarii (2)

De documentația MSDN:

performanța de o concatenare de funcționare pentru un Șir sau StringBuilder obiect depinde de cât de des o alocare de memorie apare. Un Șir de concatenare funcționarea întotdeauna alocă memorie, întrucât un StringBuilder concatenare funcțiune numai alocă memorie în cazul în care StringBuilder obiect tampon este prea mic pentru a găzdui noile date. În consecință, clasa String este de preferat pentru o concatenare de funcționare dacă un număr fix de Șir de obiecte sunt concatenate. În acest caz, individul înlănțuire de operațiuni ar putea fi chiar combinate într-o singură operațiune de compilator. Un StringBuilder obiect este de preferat pentru o concatenare de funcționare în cazul în care un număr arbitrar de siruri de caractere sunt concatenate; de exemplu, dacă o buclă concateneaza un număr aleatoriu de siruri de caractere de intrare de utilizator.

Comentarii (0)

Am fugit repede niște criterii de performanță, iar pentru 100.000 de operațiuni medie de peste 10 pârtii, prima metodă (String Constructor) are aproape jumătate din timpul celui de-al doilea (String Format).

Deci, dacă acest lucru este rar, nu't contează. Dar dacă este o operațiune comună, atunci poate doriți să utilizați prima metodă.

Comentarii (0)

M-aș aștepta String.Format pentru a fi mai lent - are pentru a analiza șir și apoi înlănțui ea.

Cateva note:

  • Format este calea de a merge pentru șirurile vizibile în aplicații profesionale; aceasta evită localizare bug-uri
  • Dacă știi lungimea șir rezultat în prealabil, utilizați StringBuilder(Int32) constructor pentru a predefini capacitate
Comentarii (0)

Dacă numai pentru că șir.Format nu't mai exact ceea ce ai putea crede, aici este o reluare a testelor 6 ani mai târziu, pe Net45.

Concat este încă cel mai rapid, dar chiar l's mai mult de 30% diferenta. StringBuilder și Format diferă de abia 5-10%. Am variații de 20% de a rula testele de câteva ori.

De milisecunde, un milion de iterații:

  • Concatenare: 367
  • New stringBuilder pentru fiecare cheie: 452
  • În Cache StringBuilder: 419
  • string.Format: 475

Lectia pe care am lua este ca diferenta de performanta este banal și deci nu ar trebui't opri tu ai scris cel mai simplu de citit codul poți. Care pentru bani este adesea, dar nu întotdeauna a + b + c`.


const int iterations=1000000;
var keyprefix= this.GetType().FullName;
var maxkeylength=keyprefix + 1 + 1+ Math.Log10(iterations);
Console.WriteLine("KeyPrefix \"{0}\", Max Key Length {1}",keyprefix, maxkeylength);

var concatkeys= new string[iterations];
var stringbuilderkeys= new string[iterations];
var cachedsbkeys= new string[iterations];
var formatkeys= new string[iterations];

var stopwatch= new System.Diagnostics.Stopwatch();
Console.WriteLine("Concatenation:");
stopwatch.Start();

for(int i=0; i
Comentarii (1)

Cred că în cele mai multe cazuri de acest gen claritate, și nu eficiența, ar trebui să fie cea mai mare problema ta. Dacă nu're strivire împreună tone de siruri de caractere, sau de a construi ceva pentru o putere mai mică dispozitivul mobil, acest lucru, probabil, a câștigat't face mai mult de un dinte în viteză.

Am'am constatat că, în cazurile în care nu'm construi siruri de caractere într-o destul de liniar, a face, fie direct înlănțuirilor sau folosind StringBuilder este cea mai bună opțiune. Am sugera acest lucru în cazurile în care majoritatea șir pe care le're clădirea este dinamic. Deoarece foarte puțin din textul este static, cel mai important lucru este că l's clară în cazul în care fiecare bucată de text dinamic este pus în cazul în care acesta trebuie actualizat în viitor.

Pe de altă parte, dacă te're vorbesc despre o bucată mare de text static cu doua sau trei variabile în ea, chiar dacă-l's un pic mai puțin eficient, cred claritatea puteți câștiga din șir.Formatul în valoare de ea. Am folosit mai devreme în această săptămână, atunci când au de a plasa un pic de text dinamic în centrul de o 4 pagini de documente. L'll fi mai ușor pentru a actualiza acea bucată de text dacă într-o singură bucată decât a fi nevoie pentru a actualiza trei piese pe care le înlănțui împreună.

Comentarii (1)

Șir.Foloseste formatul StringBuilder intern...deci logic care duce la ideea că ar fi un pic mai puțin performante din cauza mai mult deasupra capului. Cu toate acestea, un simplu șir de concatenare este cea mai rapida metoda de injectare o coardă între două others...by un grad semnificativ. Această probă a fost demonstrat prin Rico Mariani în primul său Test de Performanță, cu ani în urmă. Simplul fapt este că înlănțuirilor...atunci când numărul de piese de coarde este cunoscut (fără a se limita..ai putea înlănțui o mie de piese...atâta timp cât știi întotdeauna 1000 piese)...sunt întotdeauna mai repede decât StringBuilder sau Șir de caractere.Format. Ele pot fi efectuate cu o singură alocare de memorie o serie de memorie de copii. Aici este dovada

Și aici este codul actual pentru un Șir de caractere.Concat metode, care în cele din urmă apel FillStringChecked care utilizează pointeri la memorie copie (extras prin Reflector):

public static string Concat(params string[] values)
{
    int totalLength = 0;

    if (values == null)
    {
        throw new ArgumentNullException("values");
    }

    string[] strArray = new string[values.Length];

    for (int i = 0; i < values.Length; i++)
    {
        string str = values[i];
        strArray[i] = (str == null) ? Empty : str;
        totalLength += strArray[i].Length;

        if (totalLength < 0)
        {
            throw new OutOfMemoryException();
        }
    }

    return ConcatArray(strArray, totalLength);
}

public static string Concat(string str0, string str1, string str2, string str3)
{
    if (((str0 == null) && (str1 == null)) && ((str2 == null) && (str3 == null)))
    {
        return Empty;
    }

    if (str0 == null)
    {
        str0 = Empty;
    }

    if (str1 == null)
    {
        str1 = Empty;
    }

    if (str2 == null)
    {
        str2 = Empty;
    }

    if (str3 == null)
    {
        str3 = Empty;
    }

    int length = ((str0.Length + str1.Length) + str2.Length) + str3.Length;
    string dest = FastAllocateString(length);
    FillStringChecked(dest, 0, str0);
    FillStringChecked(dest, str0.Length, str1);
    FillStringChecked(dest, str0.Length + str1.Length, str2);
    FillStringChecked(dest, (str0.Length + str1.Length) + str2.Length, str3);
    return dest;
}

private static string ConcatArray(string[] values, int totalLength)
{
    string dest = FastAllocateString(totalLength);
    int destPos = 0;

    for (int i = 0; i < values.Length; i++)
    {
        FillStringChecked(dest, destPos, values[i]);
        destPos += values[i].Length;
    }

    return dest;
}

private static unsafe void FillStringChecked(string dest, int destPos, string src)
{
    int length = src.Length;

    if (length > (dest.Length - destPos))
    {
        throw new IndexOutOfRangeException();
    }

    fixed (char* chRef = &dest.m_firstChar)
    {
        fixed (char* chRef2 = &src.m_firstChar)
        {
            wstrcpy(chRef + destPos, chRef2, length);
        }
    }
}

Deci, atunci:

string what = "cat";
string inthehat = "The " + what + " in the hat!";

Bucurați-vă de!

Comentarii (1)

Oh, de asemenea, cel mai rapid ar fi:

string cat = "cat";
string s = "The " + cat + " in the hat";
Comentarii (4)

În ambele cazuri de mai sus, vreau să vă injectați unul sau mai multe siruri de caractere în mijlocul unui șablon predefinit string.

Caz în care, aș sugera Șir.Formatul este cel mai rapid pentru că este de design pentru exact același scop.

Comentarii (0)

Depinde. Pentru siruri de caractere mici cu câteva înlănțuirilor, l's, de fapt, mai repede doar pentru a adăuga la siruri de caractere.

String s = "String A" + "String B";

Dar pentru mai mare string (foarte, foarte mari, siruri de caractere), l's-apoi mai eficientă de a utiliza StringBuilder.

Comentarii (0)

Este într-adevăr depinde de modelul dvs. de utilizare. Detaliate de referință între șir de caractere.Se alăture", "string,Concat" și " string.Format poate fi găsit aici: Șir de caractere.Format E't Potrivit pentru exploatare forestiera Intensiva

Comentarii (0)

Aș sugera să nu, deoarece Șir.Format nu a fost conceput pentru concatenare, a fost de design pentru formatarea de ieșire de diferite intrări, cum ar fi o întâlnire.

String s = String.Format("Today is {0:dd-MMM-yyyy}.", DateTime.Today);
Comentarii (0)