добавление строк в c#, как это делает компилятор?

A = string.Concat("abc","def") 

B = "abc" + "def"

A против B

как компилятор обрабатывает эти строки?

спасибо!

6 ответов


первое, что я сделал, когда присоединился к команде компилятора C#, это переписал оптимизатор для конкатенаций строк. Благополучные времена.

как уже отмечалось, конкаты строк постоянных строк выполняются во время компиляции. Непостоянные строки делают некоторые причудливые вещи:

a + b --> String.Concat(a, b)
a + b + c --> String.Concat(a, b, c)
a + b + c + d --> String.Concat(a, b, c, d)
a + b + c + d + e --> String.Concat(new String[] { a, b, c, d, e })

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

вот интересный. Предположим, у вас есть метод M, который возвращает строку:

s = M() + "";

Если M () возвращает null, то результатом является пустая строка. (null + empty пусто.) Если M не возвращает null, то результат не изменяется путем конкатенации пустой строки. Поэтому это фактически оптимизировано как не вызов String.Функция concat вообще! Он становится

s = M() ?? ""

аккуратно, а?



в C#, оператор сложения для строк-это просто синтаксический сахар для строки.Функция concat. Это можно проверить, открыв выходную сборку в reflector.

еще одна вещь, чтобы отметить, если у вас есть строковые литералы (или константы) в вашем коде, например, в Примере, компилятор даже изменяет это на B = "abcdef".

но, если вы используете String.Concat С двумя строковыми литералами или константами String.Concat все равно будет вызываться, пропуская оптимизацию, и поэтому + операция будет быстрее.

Итак, подводя итог:

stringA + stringB становится String.Concat(stringA, stringB).
"abc" + "def" становится "abcdef"
String.Concat("abc", "def") остается одно и то же

что-то еще, я просто должен был попробовать:

в C++ / CLI,"abc" + "def" + "ghi " фактически переводится на String.Concat(String.Concat("abc", "def"), "ghi")


фактически, B разрешается во время компиляции. Вы в конечном итоге с B = "abcdef" тогда как для A конкатенация откладывается до времени выполнения.


в данном конкретном случае они фактически идентичны. Компилятор преобразует второй вариант, используя + оператор, в вызов Concat, первый вариант.

Ну, то есть, если две фактически содержали строковые переменные, которые были объединены.

этот код:

B = "abc" + "def";

фактически превращается в это, без конкатенации вообще:

B = "abcdef";

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

, если вы должны были использовать что-то вроде этого:
A = String.Concat(stringVariable1, stringVariable2);
B = stringVariable1 + stringVariable2;

тогда эти два будут генерировать один и тот же код.

однако я хотел бы точно знать, что сказали эти "многие", поскольку я думаю, что это что-то другое.

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

например, если вы делаете это:

String s = "test";
for (int index = 1; index <= 10000; index++)
    s = s + "test";

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

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

тогда как следующий код:

StringBuilder sb = new StringBuilder("test");
for (int index = 1; index <= 10000; index++)
    sb.Append("test");

вместо этого будет использовать внутренний буфер, который больше, чем нужно, просто на случай, если вам нужно добавить в него больше текста. Когда этот буфер заполнится, будет выделен новый, который больше, а старый останется для сбора мусора.

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

кроме этого, я бы постарался не фокусироваться слишком много на "вариант кода X лучше, чем Y", помимо того, что у вас уже есть опыт. Например, я использую StringBuilder сейчас только потому, что я знаю об этом случае, но это не означает, что весь код, который я пишу, который его использует, действительно нуждается в нем.

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


если строки являются литералами, как в вашем вопросе, то конкатенация строк, назначенных B будет сделано во время компиляции. Ваш пример переводится как:

string a = string.Concat("abc", "def");
string b = "abcdef";

если строки не являются литералами, компилятор переведет + оператор в Concat звонок.

так это...

string x = GetStringFromSomewhere();
string y = GetAnotherString();

string a = string.Concat(x, y);
string b = x + y;

...переводится на это во время компиляции:

string x = GetStringFromSomewhere();
string y = GetAnotherString();

string a = string.Concat(x, y);
string b = string.Concat(x, y);