С# оптимизирует конкатенацию строковых литералов?
Например, знает ли компилятор для перевода
string s = "test " + "this " + "function";
к
string s = "test this function";
и, таким образом, избежать удара производительности с помощью конкатенации строк?
Ответы
Ответ 1
Да. Это гарантируется спецификацией С#. Это в разделе 7.18 (спецификации С# 3.0):
Всякий раз, когда выражение выполняет требования, перечисленные выше, выражение оценивается в время компиляции. Это справедливо, даже если выражение является подвыражением более крупное выражение, содержащее непостоянные конструкции.
( "Требования, перечисленные выше" включают в себя оператор +, применяемый к двум константным выражениям.)
См. также этот вопрос.
Ответ 2
Просто примечание к связанной теме - компилятор С# также будет "оптимизировать" несколько конкатенаций с использованием нелитералов с использованием оператора "+
" для одного вызова многопараметрической перегрузки String.Concat().
So
string result = x + y + z;
компилируется в нечто эквивалентное
string result = String.Concat( x, y, z);
а не более наивная возможность:
string result = String.Concat( String.Concat( x, y), z);
Ничто не разрушило землю, но просто захотело добавить этот бит в обсуждение оптимизации конкатенации строк. Я не знаю, соответствует ли это поведение стандарту языка или нет.
Ответ 3
Да.
С# не только оптимизирует конкатенацию строковых литералов, но и сводит эквивалентные строковые литералы в константы и использует указатели для ссылки на все ссылки на одну и ту же константу.
Ответ 4
Да. Вы можете явно это увидеть с помощью ILDASM.
Пример:
Здесь программа, похожая на ваш пример, за которой следует скомпилированный код CIL:
Примечание. Я использую функцию String.Concat(), чтобы увидеть, как компилятор рассматривает два разных метода конкатенации.
Программа
class Program
{
static void Main(string[] args)
{
string s = "test " + "this " + "function";
string ss = String.Concat("test", "this", "function");
}
}
ILDASM
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 3
.locals init (string V_0,
string V_1)
IL_0000: nop
IL_0001: ldstr "test this function"
IL_0006: stloc.0
IL_0007: ldstr "test"
IL_000c: ldstr "this"
IL_0011: ldstr "function"
IL_0016: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_001b: stloc.1
IL_001c: ret
} // end of method Program::Main
Обратите внимание, что в IL_0001 компилятор создал константу "проверить эту функцию" в отличие от того, как компилятор рассматривает функцию String.Concat(), которая создает константу для каждого из параметров .Concat(), а затем вызывает. Функция Concat().
Ответ 5
Из уст лошадей:
Конкатенация - это процесс добавления одной строки в конец другой строки. Когда вы объединяете строковые литералы или строковые константы с помощью оператора +, компилятор создает одну строку. Не происходит конкатенации времени выполнения. Однако строковые переменные могут быть объединены только во время выполнения. В этом случае вы должны понимать последствия работы различных подходов.
http://msdn.microsoft.com/en-us/library/ms228504.aspx
Ответ 6
Я считаю, что ответ на этот вопрос - да, но вам нужно будет посмотреть, что компилятор выплевывает... просто компилируйте и используйте рефлектор на нем: -)
Ответ 7
У меня был аналогичный вопрос, но о VB.NET вместо С#. Самый простой способ проверить это - просмотреть скомпилированную сборку в Reflector.
Ответ заключался в том, что компилятор С# и VB.NET оптимизирует конкатенацию строковых литералов.