例如,编译器是否知道如何转换
string s = "test " + "this " + "function";
string s = "test this function";
那么如何避免使用字符串拼接时的性能损耗呢?
例如,编译器是否知道如何转换
string s = "test " + "this " + "function";
string s = "test this function";
那么如何避免使用字符串拼接时的性能损耗呢?
关于相关主题的一则侧记——C#编译器也会使用'+
'运算符对涉及非字面量的多次字符串连接进行“优化”,将其转换为对String.Concat()方法的多参数重载的单个调用。
因此,
string result = x + y + z;
编译成等效的内容
string result = String.Concat( x, y, z);
与其采用更为天真的可能性:
string result = String.Concat( String.Concat( x, y), z);
虽然没有什么惊天动地的,但我只是想在关于字符串字面量拼接优化的讨论中添加这一点。我不知道这种行为是否由语言标准规定。
是的。
C# 不仅优化字符串字面量的拼接,还将等效的字符串字面量折叠为常量,并使用指针引用所有对同一常量的引用。
是的 - 你可以使用ILDASM显式地看到这一点。
例如:
这是一个类似于你的示例程序,其后是已编译的CIL代码:
注意:我使用String.Concat()函数只是为了看看编译器如何处理两种不同的连接方法。
程序
class Program
{
static void Main(string[] args)
{
string s = "test " + "this " + "function";
string ss = String.Concat("test", "this", "function");
}
}
ILDASM
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 3
.locals init (string V_0,
string V_1)
IL_0000: nop
IL_0001: ldstr "test this function"
IL_0006: stloc.0
IL_0007: ldstr "test"
IL_000c: ldstr "this"
IL_0011: ldstr "function"
IL_0016: call string [mscorlib]System.String::Concat(string,
string,
string)
IL_001b: stloc.1
IL_001c: ret
} // end of method Program::Main
注意在IL_0001处编译器创建了常量"test this function",而不是像对待String.Concat()函数一样-为每个.Concat()参数创建常量,然后调用.Concat()函数。
消息来源:
连接是将一个字符串添加到另一个字符串末尾的过程。当您使用 + 运算符连接字符串字面量或字符串常量时,编译器会创建单个字符串。不会发生运行时的连接。但是,只有在运行时才能连接字符串变量。在这种情况下,您应该了解各种方法的性能影响。
我有一个类似的问题,但是关于VB.NET而不是C#。验证这一点最简单的方法是在Reflector下查看编译后的程序集。
答案是,C#和VB.NET编译器都优化字符串文字的连接。
$"hello {foo}, i'm {bar}"
和$"hello {foo}" + $"i'm {bar}"
是一样的吗? - user247702string.Format
。 - Jon Skeet