2015-12-10 1 views
4

Является ли эффективным (или необходимым?), Чтобы сделать StringBuilder членом класса и использовать его в методах класса всякий раз, когда выполняется конкатенация строк?StringBuilder как член класса?

Или просто используйте новый StringBuidler() перед такими операциями?

Я подозреваю, что он эффективен, если есть StringBuilder, готовый к использованию.

Xing

+11

Новый 'StringBuilder' не дорого для initia Лиза. Не оптимизируйте неправильные вещи –

+2

Зависит от прецедента. Но 'StringBuilder' не стоит слишком дорого выделять. И если это проблема, вы всегда можете создать пул строителей для использования. Как правило, создание элемента уровня класса будет больно, если вы хотите обеспечить безопасность потока. –

+0

На самом деле это зависит. Если у вас много методов (например, сотни, что делает для меня не слишком много смысла), то наличие члена имеет смысл ... но до тех пор, пока это происходит только в несколько раз, накладные расходы действительно незначительны. – gregkalapos

ответ

4

Это интересный вопрос, и один, который был researched.

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

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

Следующий код из linked article делает весьма искусственный тест производительности:

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

class Program 
{ 
    static string Method1() 
    { 
     StringBuilder builder = new StringBuilder(); 
     foreach (string value in _array) 
      builder.Append(value); 
     return builder.ToString(); 
    } 

    static StringBuilder _builder = new StringBuilder(); 

    static string Method2() 
    { 
     StringBuilder builder = _builder; 
     builder.Clear(); 
     foreach (string value in _array) 
      builder.Append(value); 
     return builder.ToString(); 
    } 

    static string[] _array = { "dot", "net", "perls", "string", "array" }; 
    const int _max = 1000000; 
    static void Main() 
    { 
     Method1(); 
     Method2(); 

     // Version 1: use new StringBuilder each time. 
     var s1 = Stopwatch.StartNew(); 
     for (int i = 0; i < _max; i++) 
     { 
      Method1(); 
     } 
     s1.Stop(); 

     // Version 2: reuse a single StringBuilder instance. 
     var s2 = Stopwatch.StartNew(); 
     for (int i = 0; i < _max; i++) 
     { 
      Method2(); 
     } 
     s2.Stop(); 
     Console.WriteLine(s1.Elapsed.TotalMilliseconds); 
     Console.WriteLine(s2.Elapsed.TotalMilliseconds); 
     Console.Read(); 
    } 
} 

В результате (я просто запустить его сам):

  • Многократное распределение: 146,21
  • StringBuilder в поле: 98.96
+3

Это один из этих вопросов по микрооптимизации, которые не имеют значения на практике. В большинстве случаев другие аргументы должны иметь значение, как читаемость, ремонтопригодность, (thread-) безопасность, доступность, инкапсуляция, повторное использование. Кроме того, часто есть другие вещи, которые можно улучшить. Я не вижу причины вызывать метод, который использует большой цикл миллионы раз. Вместо этого я мог бы использовать один цикл с большим счетчиком циклов (например). –

+0

@TimSchmelter: Я полностью согласен - но, как академический вопрос, все еще интересно. Я сказал в своем ответе, что практически в любой реальной ситуации это не будет актуальным. – Baldrick

+1

Да, но то, что останется в вашей памяти, заключается в том, что для производительности по-настоящему лучше использовать один «StringBuilder», который в действительности не соответствует действительности. Таким образом, люди будут использовать член класса 'StringBuilder' без увеличения производительности, но с возможными проблемами с потоками в будущем или просто неправильными результатами, если один из методов манипулирует содержимым, а другой метод его не ожидает. Он вводит ненужную сложность и зависимости. «StringBuilder» - это инструмент для создания String. Это может быть сохранено как поле в классе, поскольку оно является свойством этого типа, а не '' StringBuilder''. –