StringBuilder C#

StringBuilder C#

Всем доброго времени суток, на связи Алексей Гулынин. В прошлой статье мы узнали про явное и неявное преобразование в C#. В данной статье я бы хотел поговорить про класс StringBuilder в C#. Вначале разберем то, как мы обычно складываем строки.

Для сложения (склейки) строк в C# перегружен оператор "+". Это оператор конкатенации строк. Допустим у нас имеется 4 строки, которые мы хотим склеить в одну. Напишем пример кода:

static void Main(string[] args)
{
	string s1 = "Hello"; string s2 = "my"; string s3 = "dear"; string s4 = "friend";
	string result = s1 + ", " + s2 + " " + s3 + " " + s4;
	Console.WriteLine(result);
	Console.ReadLine();
}

Код работает, результат выводится. Но оптимально ли так делать? Давайте разберем другой способ склеивания строк — это как раз использование класса StringBuilder. Напишем код:

static void Main(string[] args)
{
	string s1 = "Hello"; string s2 = "my"; string s3 = "dear"; string s4 = "friend";
	StringBuilder result = new StringBuilder();
	result.AppendLine(s1 + ", " + s2 + " " + s3 + " " + s4);
	Console.WriteLine(result);
	Console.ReadLine();
}

Вроде бы отличия нет. Результат выводится одинаковый в обоих случаях. Главный вопрос — одинаковая ли производительность у обоих способов?

Первый способ сборки строк в .NET плох. Объекта класса String является неизменяемым объектом (immutable object). Каждый раз, когда мы выполняем операцию — мы не меняем существующие строки, а создаём новую строку. Объясню подробнее на первом примере. У нас сначала будет создана строка "Hello, ", затем строка "Hello, my", затем строка "Hello, my ", затем строка "Hello, my dear", "Hello, my dear " и "Hello, my dear friend". Все эти строки будут висеть в памяти, что нам совсем не нужно. Для решения данной проблемы как раз и используется класс StringBuilder, который представляет из себя изменяемую строку. Здесь вместо оператора конкатенации можно использовать методы Append() и AppendLine(), которые будут не новый объект создавать, а модифицировать существующий.

Второй способ потребляет меньше памяти и работает гораздо быстрее.

Попробуем на следующим примере продемонстрировать разницу в производительности данных методов:

static void Main(string[] args)
{
	{
		string result = "";
		DateTime dt = DateTime.Now;
		for (int i = 1; i < 100000; i++)
		{
			result = result + i.ToString();
		}
		Console.WriteLine("Время скрипта {0}", DateTime.Now - dt);
		Console.ReadLine();
		//Время скрипта было 15.7303146 секунд
	}
	{
		StringBuilder result = new StringBuilder();
		DateTime dt = DateTime.Now;
		for (int i = 1; i < 100000; i++)
		{
			result.Append(i.ToString());
		}
		Console.WriteLine("Время скрипта {0}", DateTime.Now - dt);
		Console.ReadLine();
		//Время скрипта было 0.020004 секунд
	}
}

Что мы делаем в данном скрипте: в цикле из 100000 элементов мы к каждой строке прибавляем число, т.е. у нас будет такие строки на каждой итерации: 1, 12, 123, 1234 и т.д. (происходит склейка строк). В первом случае у нас будет создано 100000 строк (объектов), которые будут висеть в памяти. Во втором случае будет изменяться существующий объект.

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

В качестве домашнего задания протестируйте работу данного скрипта.


Комментарии:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *