добавление строк в 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);