Stringbuilder против строки concat

В моем проекте я перебираю результат dataview.

 string html =string.empty;
 DataView dV = data.DefaultView;
 for(int i=0;i< dV.Count;i++)
 {
     DataRowView rv = dV[i];
     html += rv.Row["X"].Tostring();
 }

Количество строк в dV всегда будет 3 или 4.

Лучше ли использовать строку concat + = opearator или StringBuilder для этого случая и почему?

Ответ 1

Я бы использовал StringBuilder здесь, просто потому, что он описывает, что вы делаете.

Для простой конкатенации 3 или 4 строк это, вероятно, не будет иметь существенных отличий, а конкатенация строк может быть даже немного быстрее - но если вы ошибаетесь и есть много строк, начнется StringBuilder становится намного более эффективным, и он всегда более подробно описывает, что вы делаете.

В качестве альтернативы используйте что-то вроде:

string html = string.Join("", dv.Cast<DataRowView>()
                                .Select(rv => rv.Row["X"]));

Обратите внимание, что у вас нет никакого разделителя между строками на данный момент. Вы уверены, что хотите? (Также обратите внимание, что ваш код не имеет большого смысла на данный момент - вы не используете i в цикле. Почему?)

У меня есть статья о конкатенации строк, которая более подробно описывает, почему стоит использовать StringBuilder и когда.

EDIT: для тех, кто сомневается, что конкатенация строк может быть быстрее, вот тест - с преднамеренно "скверными" данными, но просто для того, чтобы доказать это:

using System;
using System.Diagnostics;
using System.Text;

class Test
{
    static readonly string[] Bits = { 
        "small string",
        "string which is a bit longer",
        "stirng which is longer again to force yet another copy with any luck"
    };

    static readonly int ExpectedLength = string.Join("", Bits).Length;

    static void Main()        
    {
        Time(StringBuilderTest);
        Time(ConcatenateTest);
    }

    static void Time(Action action)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        // Make sure it JITted
        action();
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < 10000000; i++)
        {
            action();
        }
        sw.Stop();
        Console.WriteLine("{0}: {1} millis", action.Method.Name,
                          (long) sw.Elapsed.TotalMilliseconds);
    }

    static void ConcatenateTest()
    {
        string x = "";
        foreach (string bit in Bits)
        {
            x += bit;
        }
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }

    static void StringBuilderTest()
    {
        StringBuilder builder = new StringBuilder();
        foreach (string bit in Bits)
        {
            builder.Append(bit);
        }
        string x = builder.ToString();
        // Force a validation to prevent dodgy optimizations
        if (x.Length != ExpectedLength)
        {
            throw new Exception("Eek!");
        }
    }
}

Результаты на моей машине (скомпилированы с /o+ /debug-):

StringBuilderTest: 2245 millis
ConcatenateTest: 989 millis

Я запускаю это несколько раз, включая изменение порядка тестов, и результаты согласуются.

Ответ 2

StringBuilder рекомендуется.. почему вы не делаете анализ для себя, а затем решаете, что лучше для вас.

var stopWatch=new StopWatch();
stopWatch.Start();
string html =string.empty;
        DataView dV = data.DefaultView;
        for(int i=0;i< dV.Count;i++)
        {
           html += dV.Row["X"].Tostring();
        } 
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());

var stopWatch=new StopWatch();
stopWatch.Start();
string html =new StringBuilder();
        DataView dV = data.DefaultView;
        for(int i=0;i< dV.Count;i++)
        {
           html.Append(dV.Row["X"].ToString());
        } 
var finalHtml=html.ToString();
stopWatch.Stop();
Console.Write(stopWatch.EllapsedMilliseconds());

Ответ 3

Из документации:

Класс String предпочтительнее для операции конкатенации, если фиксированное число объектов String конкатенируется. В этом случае отдельные операции конкатенации могут быть даже объединены в одиночная работа компилятором.

Объект StringBuilder предпочтительнее для операции конкатенации, если произвольное число строк конкатенировано; например, если loop объединяет случайное число строк пользовательского ввода.

Итак, в вашем случае я бы сказал, что String лучше.

EDIT:

Это бесконечная дискурсивность, так или иначе, я бы рекомендовал вам проверить, сколько операций у вас есть в среднем, и проверить эффективность для каждого из них, чтобы сравнить результаты.

Отметьте хорошую ссылку относительно этой проблемы, включая некоторый код проверки производительности.

Ответ 4

StringBuilder. Строка неизменно запоминается!

РЕДАКТИРОВАНИЕ: для 3-4 рядов конкатенация будет предпочтительным выбором, как сказал Джон Скит в своем ответе

Ответ 5

StringBuilder. Он изменчив. Это должно значительно снизить нагрузку на распределитель памяти: -)

Строковый экземпляр является неизменным. Вы не можете изменить его после создано.     Любая операция, которая появляется для изменения строки, возвращает новый экземпляр.

Ответ 6

stringbuilder - это то, что вы ищете. В общем случае, если есть функция для некоторой работы, попробуйте использовать ее вместо написания некоторой процедуры, которая выполняет почти ту же работу.