С# оптимизирует конкатенацию строковых литералов?

Например, знает ли компилятор для перевода

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 оптимизирует конкатенацию строковых литералов.