令人惊讶的是,这取决于。
如果你在方法中这样做:
void Foo() {
String one = "1";
String two = "2";
String result = one + two + "34";
Console.Out.WriteLine(result);
}
然后编译器似乎使用@Joachim 回答时使用String.Concat 发出代码(顺便说一句,给他+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 生成的内容进行。
最后,关于实习,常量和文字都是实习的,但实习的值是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 次迭代,每次都会产生一个新的字符串实例:
public class Program
{
static void Main(string[] args)
{
string result = "";
for (int i = 0; i < 10; i++)
result += "a";
Console.ReadKey();
}
}
但是(同样令人惊讶的是)多个连续的连接被编译器组合成一个单一的多字符串连接。例如,这个程序也只产生 12 个字符串实例!这是因为“Even if you use several + operators in one statement, the string content is copied only once.”
public class Program
{
static void Main(string[] args)
{
string result = "";
for (int i = 0; i < 10; i++)
result += "a" + result;
Console.ReadKey();
}
}