Сколько объектов String будет создано при использовании знака плюса в приведенном ниже коде?
String result = "1" + "2" + "3" + "4";
Если бы это было так, как показано ниже, я бы сказал три объекта String: «1», «2», «12».
String result = "1" + "2";
Я также знаю, что объекты String кэшируются в пуле / таблице String Intern для повышения производительности, но вопрос не в этом.
Ответы:
Удивительно, но это зависит от обстоятельств.
Если вы сделаете это методом:
то компилятор, кажется, испускает код, используя,
String.Concat
как ответил @Joachim (+1 к нему, кстати).Если вы определяете их как константы , например:
или как литералы , как в исходном вопросе:
тогда компилятор устранит эти
+
признаки. Это эквивалентно:Кроме того, компилятор удалит посторонние константные выражения и выдаст их только в том случае, если они используются или открываются. Например, эта программа:
Генерирует только одну строку - константу
result
(равную «1234»).one
иtwo
не отображаются в результирующем IL.Имейте в виду, что во время выполнения могут быть дальнейшие оптимизации. Я просто ориентируюсь на то, что производится ИЛ.
Наконец, что касается интернирования, константы и литералы интернируются, но интернированное значение является результирующим постоянным значением в IL, а не литералом. Это означает, что вы можете получить даже меньше строковых объектов, чем ожидаете, поскольку несколько идентично определенных констант или литералов фактически будут одним и тем же объектом! Об этом свидетельствует следующее:
В случае, когда строки объединяются в цикл (или иным образом динамически), вы получаете одну дополнительную строку на объединение. Например, следующее создает 12 экземпляров строки: 2 константы + 10 итераций, каждая из которых приводит к новому экземпляру String:
Но (что также удивительно), несколько последовательных конкатенаций объединяются компилятором в одну многострочную конкатенацию. Например, эта программа также производит только 12 экземпляров строк! Это потому, что « Даже если вы используете несколько операторов + в одном операторе, содержимое строки копируется только один раз ».
источник
string s = ""; for (int i = 0; i < n; i++) s += "a";
Крис Шейн ответил очень хорошо. Как человек, который написал оптимизатор конкатенации строк, я бы просто добавил два дополнительных интересных момента.
Во-первых, оптимизатор конкатенации по существу игнорирует и скобки, и левую ассоциативность, когда это можно сделать безопасно. Предположим, у вас есть метод M (), который возвращает строку. Если вы скажете:
то компилятор считает, что оператор сложения является левоассоциативным, и поэтому это то же самое, что:
Но это:
такой же как
так что это конкатенация постоянной строки
"CD"
сM()
.Фактически, оптимизатор конкатенации понимает, что конкатенация строк является ассоциативной , и генерирует
String.Concat(M(), "AB")
для первого примера, даже если это нарушает левую ассоциативность.Вы даже можете сделать это:
и мы по-прежнему будем генерировать
String.Concat(M(), "EF", M())
.Второй интересный момент заключается в том, что нулевые и пустые строки оптимизируются. Итак, если вы сделаете это:
ты получишь
String.Concat(M(), M())
Тогда возникает интересный вопрос: а что насчет этого?
Мы не можем оптимизировать это до
потому что
M()
может вернуть null, ноString.Concat(M(), null)
вернет пустую строку, еслиM()
вернет null. Вместо этого мы сокращаемв
Тем самым демонстрируя, что конкатенация строк вообще не требует вызова
String.Concat
.Для дальнейшего чтения по этому вопросу см.
Почему String.Concat не оптимизирован для StringBuilder.Append?
источник
("C" + "D") + M())
порождаетString.Concat("CD", M())
, а неString.Concat(M(), "AB")
. И ниже(M() + "E") + (null + M())
должно генерироватьсяString.Concat(M(), "E", M())
, а неString.Concat(M(), M())
.Я нашел ответ в MSDN. Один.
Как: объединить несколько строк (Руководство по программированию на C #)
источник
Только один. Компилятор C # сворачивает строковые константы и, следовательно, по существу компилируется до
источник
Я сомневаюсь, что это предусмотрено каким-либо стандартом или спецификацией. Одна версия, вероятно, может делать что-то отличное от другой.
источник
Во-первых, поскольку они статичны, компилятор сможет оптимизировать их до одной строки во время компиляции.
Если бы они были динамическими, они были бы оптимизированы для одного вызова String.Concat (строка, строка, строка, строка) .
источник