Подтвердить что ты не робот

Возвращаемые значения String или StringBuilder?

Если я строю строку с использованием объекта StringBuilder в методе, имеет смысл:

Верните объект StringBuilder и позвольте вызывающему коду вызвать ToString()?

return sb;

ИЛИ Верните строку, вызвав ToString() самостоятельно.

return sb.ToString();

Я предполагаю, что это имеет значение, если мы возвращаем небольшие или большие строки. Что было бы уместно в каждом случае? Спасибо заранее.

Изменить: Я не планирую дальше изменять строку в вызывающем коде, но хорошая точка Колин Бернетт.

В основном, эффективнее ли возвращать объект StringBuilder или строку? Будет ли возвращена ссылка на строку или копия?

4b9b3361

Ответ 1

Верните StringBuilder, если вы собираетесь изменить строку, иначе верните строку. Это вопрос API.

Относительно эффективности. Поскольку это неопределенный/общий вопрос без каких-либо особенностей, я думаю, что mutable vs. immutable более важен, чем производительность. Mutability - это проблема API, позволяющая вашему API возвращать модифицируемые объекты. Длина строки не имеет отношения к этому.

Это сказало. Если вы посмотрите на StringBuilder.ToString с рефлектором:

public override string ToString()
{
    string stringValue = this.m_StringValue;
    if (this.m_currentThread != Thread.InternalGetCurrentThread())
    {
        return string.InternalCopy(stringValue);
    }
    if ((2 * stringValue.Length) < stringValue.ArrayLength)
    {
        return string.InternalCopy(stringValue);
    }
    stringValue.ClearPostNullChar();
    this.m_currentThread = IntPtr.Zero;
    return stringValue;
}

Вы можете видеть, что он может сделать копию, но если вы измените ее с помощью StringBuilder, тогда она сделает копию (это то, что я могу сказать о точке m_currentThread, потому что Append проверяет это и копирует ее, если она не соответствует текущий поток).

Я думаю, что конец этого заключается в том, что если вы не модифицируете StringBuilder, вы не копируете строку, а длина не имеет отношения к эффективности (если вы не нажмете на это 2-е место).

ОБНОВЛЕНИЕ

System.String - это класс, который означает, что он является ссылочным типом (в отличие от типа значения), поэтому "string foo;" по существу, является указателем. (Когда вы передаете строку в метод, она передает указатель, а не копию.) System.String изменена внутри mscorlib, но неизменна вне ее, а именно, как StringBuilder может манипулировать строкой.

Итак, когда вызывается ToString(), он возвращает свой внутренний строковый объект по ссылке. На данный момент вы не можете изменить его, потому что ваш код не находится в mscorlib. Установив поле m_currentThread равным нулю, любые дальнейшие операции над StringBuilder заставят его скопировать строковый объект, чтобы он мог быть изменен и не изменять строковый объект, который он возвращал в ToString(). Рассмотрим это:

StringBuilder sb = new StringBuilder();
sb.Append("Hello ");

string foo = sb.ToString();

sb.Append("World");

string bar = sb.ToString();

Если StringBuilder не сделал копию, то в конце foo будет "Hello World", потому что StringBuilder изменил его. Но поскольку он сделал копию, тогда foo по-прежнему просто "Hello", а bar - "Hello World".

Означает ли это всю обратную/ссылочную вещь?

Ответ 2

Я не думаю, что производительность должна быть фактором в этом вопросе. В любом случае, кто-то будет называть sb.ToString(), чтобы ваш сайт попал в цель.

Более важным вопросом является то, что является намерением метода и цели. Если этот метод является частью построителя, вы можете вернуть построитель строк. В противном случае я бы вернул строку.

Если это часть открытого API, я бы склонялся к возврату строки вместо строителя.

Ответ 3

Я бы сказал, что метод должен возвращать sb.ToString(). Если логика, связанная с созданием объекта StringBuilder(), должна измениться в будущем, мне будет понятно, что она будет изменена в методе не в каждом сценарии, который вызывает этот метод, а затем продолжает делать что-то еще

Ответ 4

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

Строки всегда хранятся в куче, поэтому у вас будет ссылка, если тип возврата - строка. Однако вы не можете рассчитывать на две одинаковые строки, чтобы иметь одинаковые ссылки. В общем, безопасно думать о строке, как если бы это был тип значения, даже если он является ссылочным типом.

Ответ 5

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

Подумав об этом на данный момент, ответ намного яснее. Вопрос о том, что нужно вернуть, действительно отвечает на вопрос. Обратный объект должен быть строкой. Причина в том, что если вы задаете вопрос: "Есть ли причина возвращать объект StringBuilder, когда строка будет работать?" тогда ответ - нет. Если возникла причина, то возвращающая строка не может быть и речи, потому что необходимы методы и свойства строкового конструктора.

Ответ 6

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

Ответ 7

Я бы возвратил string почти во всех ситуациях, особенно если этот метод является частью общедоступного API.

Исключение будет, если ваш метод является лишь частью более крупного частного процесса "строителя", а вызывающий код будет делать дальнейшие манипуляции. В таком случае я, возможно, подумаю о возврате StringBuilder.

Ответ 8

Поскольку вы больше не собираетесь его изменять

return sb.ToString();

должен быть наиболее эффективным

Ответ 9

Верните sb.ToString(). Ваш метод должен сосредоточиться только на том, что нужно (в этом случае построить мне строку), а не возвращаться для дальнейшей обработки IMO, вы можете столкнуться со всеми проблемами, с которыми он не будет удален.

Ответ 10

Если вам нужно добавить больше материала в строку и использовать другие связанные с ним функции, верните stringbuilder. В противном случае, если вы просто используете самую строку, верните строку.

Существуют и другие технические соображения, но это проблемы самого высокого уровня.

Ответ 11

Метод получил конкретную задачу, и его следует ожидать, чтобы завершить его и вернуть законченный результат, который не требует дальнейшей обработки. Верните только StringBuilder, когда вам это действительно нужно. В этом случае также добавьте что-то к имени метода, чтобы указать, что вы возвращаете что-то особенное.