Удивительно, но это зависит от обстоятельств.
Если вы сделаете это методом:
void Foo() {
String one = "1";
String two = "2";
String result = one + two + "34";
Console.Out.WriteLine(result);
}
то компилятор, кажется, испускает код, используя, String.Concat
как ответил @Joachim (+1 к нему, кстати).
Если вы определяете их как константы , например:
const String one = "1";
const String two = "2";
const String result = one + two + "34";
или как литералы , как в исходном вопросе:
String result = "1" + "2" + "3" + "4";
тогда компилятор устранит эти +
признаки. Это эквивалентно:
const String result = "1234";
Кроме того, компилятор удалит посторонние константные выражения и выдаст их только в том случае, если они используются или открываются. Например, эта программа:
const String one = "1";
const String two = "1";
const String result = one + two + "34";
public static void main(string[] args) {
Console.Out.WriteLine(result);
}
Генерирует только одну строку - константу result
(равную «1234»). one
и two
не отображаются в результирующем IL.
Имейте в виду, что во время выполнения могут быть дальнейшие оптимизации. Я просто ориентируюсь на то, что производится ИЛ.
Наконец, что касается интернирования, константы и литералы интернируются, но интернированное значение является результирующим постоянным значением в IL, а не литералом. Это означает, что вы можете получить даже меньше строковых объектов, чем ожидаете, поскольку несколько идентично определенных констант или литералов фактически будут одним и тем же объектом! Об этом свидетельствует следующее:
public class Program
{
private const String one = "1";
private const String two = "2";
private const String RESULT = one + two + "34";
static String MakeIt()
{
return "1" + "2" + "3" + "4";
}
static void Main(string[] args)
{
string result = "1" + "2" + "34";
// Prints "True"
Console.Out.WriteLine(Object.ReferenceEquals(result, MakeIt()));
// Prints "True" also
Console.Out.WriteLine(Object.ReferenceEquals(result, RESULT));
Console.ReadKey();
}
}
В случае, когда строки объединяются в цикл (или иным образом динамически), вы получаете одну дополнительную строку на объединение. Например, следующее создает 12 экземпляров строки: 2 константы + 10 итераций, каждая из которых приводит к новому экземпляру String:
public class Program
{
static void Main(string[] args)
{
string result = "";
for (int i = 0; i < 10; i++)
result += "a";
Console.ReadKey();
}
}
Но (что также удивительно), несколько последовательных конкатенаций объединяются компилятором в одну многострочную конкатенацию. Например, эта программа также производит только 12 экземпляров строк! Это потому, что « Даже если вы используете несколько операторов + в одном операторе, содержимое строки копируется только один раз ».
public class Program
{
static void Main(string[] args)
{
string result = "";
for (int i = 0; i < 10; i++)
result += "a" + result;
Console.ReadKey();
}
}