Дивно, але це залежить.
Якщо ви робите це методом:
void Foo() {
String one = "1";
String two = "2";
String result = one + two + "34";
Console.Out.WriteLine(result);
}
тоді компілятор, здається String.Concat
, видає код, використовуючи відповідь @Joachim (+1 до нього btw).
Якщо ви визначаєте їх як константи , наприклад:
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
не відображаються в отриманому ІР.
Майте на увазі, що під час виконання можуть бути додаткові оптимізації. Я просто переходжу до того, що виробляється ІЛ.
Нарешті, що стосується інтернування, константи та буквали є інтернованими, але значення, яке інтерновано, є отриманим постійним значенням в ІЛ, а не буквальним. Це означає, що ви можете отримати ще менше рядкових об'єктів, ніж ви очікували, оскільки кілька однаково визначених констант або літералів будуть фактично одним і тим же об’єктом! Це пояснюється наступним:
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();
}
}