Являются ли строки StringBuilder неизменяемыми? - PullRequest
6 голосов
/ 02 февраля 2009

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

Быстрый просмотр Reflector показывает, что StringBuilder.ToString () не всегда возвращает копию, иногда кажется, что она возвращает экземпляр внутренней строки. Также кажется, что используются некоторые внутренние функции для управления внутренними строками.

Так что я получу, если сделаю это?

string s = "Yo Ho Ho";
StringBuilder sb = new StringBuilder(s);
string newString = sb.ToString();
sb.Append(" and a bottle of rum.");
string newNewString = sb.ToString();

Являются ли newString и newNewString разными строковыми экземплярами или одинаковыми? Я пытался выяснить это с помощью отражателя, и я просто не совсем все понимаю.

Как насчет этого кода?

StringBuilder sb = new StringBuilder("Foo\n");
StringReader sr = new StringReader(sb.ToString());
string s = sr.ReadLine();
sb.Append("Bar\n");
s = sr.ReadLine();

Будет ли последний оператор возвращать ноль или "Bar"? И если он возвращает одно или другое, это определенное или неопределенное поведение? Другими словами, могу ли я на это положиться?

Документация по этому вопросу весьма лаконична, и я неохотно полагаюсь на наблюдаемое поведение, а не на спецификацию.

Ответы [ 4 ]

10 голосов
/ 02 февраля 2009

За пределами mscorlib любой экземпляр System.String является неизменным, точка.

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

Относительно того, возвращают ли последующие вызовы StringBuilder.ToString () один и тот же экземпляр String или другую String с тем же значением, что зависит от реализации, и вы не должны полагаться на это поведение.

4 голосов
/ 02 февраля 2009

newString и newNewString - это разные строковые экземпляры.

Хотя ToString() возвращает текущую строку, она очищает текущую переменную потока. Это означает, что в следующий раз, когда вы добавите, перед добавлением будет скопирована текущая строка.

Я не полностью уверен, что вы получите в своем втором вопросе, но s будет нулевым: если последние символы в файле являются символом (ами) завершения строки в предыдущей строке строка не считается пустой строкой между этими символами и концом файла. Строка, которая была прочитана ранее, не имеет к этому никакого значения.

3 голосов
/ 02 февраля 2009

Есть newString и newNewString разные string экземпляры или так же? Я пытался понять это через отражатель, а я просто не совсем все понимаю.

Это разные string экземпляры: newString это "Yo Ho Ho" и newNewString это "Yo Ho Ho and a bottle of rum.". strings являются неизменяемыми, и когда вы вызываете StringBuilder.ToString(), метод возвращает неизменяемое string, которое представляет текущее состояние.

Вернется ли последнее утверждение null или "Bar"? И если он возвращает один или другой Другое, это определено или не определено поведение? Другими словами, могу ли я положиться на это?

Вернется null. StringReader работает с неизменным string, который вы передали ему в конструкторе, поэтому на него не влияет то, что вы делаете с StringBuilder.

2 голосов
/ 02 февраля 2009

Цель этого класса - сделать строку изменчивой, так оно и есть на самом деле. Я верю (но не уверен), что он вернет ту же самую строку, которая входит в него, только если ничего не было сделано с этим объектом. Итак, после

String s_old = "Foo";
StringBuilder sb = new StringBuilder(s_old);
String s_new = sb.ToString();

s_old будет таким же, как s_new, но не будет в любом другом случае.

Следует отметить, что для компилятора Java автоматическое преобразование нескольких добавлений строк в операции с классом StringBuilder (или StringBuffer, который аналогичен, но даже быстрее), и я был бы очень удивлен, что компилятор .NET также не выполняет это преобразование.

...