我在C#6.0中有两个代码:
示例1:
var foo = "Some text, " +
$"some other {bar}, " +
"end text.";
示例2:
var foo = $"Some text, " +
$"some other {bar}, " +
$"end text.";
显然,这两个代码都会产生相同的结果,但第二个代码在美学上更加美观(这是我的意见,请记住每个代码都有你的。)
问题:
如果不需要$,是否有问题(性能或其他)写一个前缀为$的字符串。
修改 回答一些抱怨:
第二个是可怕的。不要对没有内插的字符串使用字符串插值符号($)。对于任何查看代码的人(或未来,更有经验的人)来说,这会让人感到困惑
这完全是您的看法,我在这里有一个团队,有10位高级C#开发人员,他们都同意第二个更清晰。
@ChetanRanpariya这不是真的。插值字符串是用于调用string.Format的语法糖,必须调用它(从而影响性能)。
你需要提供证明你在说什么。
答案 0 :(得分:5)
$
创建一个插值字符串,与使用String.Format
相同。如果将+
与字符串文字一起使用,则编译器会优化代码以避免连接在一起。使用插值字符串可能会阻止此优化。
修改强>
性能和文字优化测试
好吧,我刚刚测试了这个,似乎没有任何性能问题。显然,如果没有$
,编译器会忽略{}
并且不使用String.Format。我的测试结果显示在600万个构造50长度字符串的循环中。
String.Format
:23700 ms $"a{null}"
+
:22650 ms $"a"
+
:13 ms "a"
+
:13 ms "a"
与+
连接:700毫秒另外,看IL也没什么区别。因此,性能方面,您发布的代码执行和优化相同,$
被忽略,只是使用{}
时的一个因素。
<强>语法强>
当然可以讨论这是否是好的语法。我可以想到支持和反对的论据。
赞成
$
已经存在,则添加新参数会更容易缺点
对我来说,倾斜点是我看到$
并希望看到{}
和一个参数。如果我看不到我期望看到的东西,它会导致认知失调。另一方面,我可以想象它提供的流动性可能会出现这种情况。可能很远,它取决于开发组和目标。
答案 1 :(得分:1)
这很容易做一些简单的诊断。 Maccettura在评论中显示,当它被编译时没有区别,因为它只为每个字符串调用一次String.Format而不管额外的插值,但是这个测试也会支持它。
int rounds = 50;
int timesToCreateString = 50000;
Stopwatch sw = new Stopwatch();
double first = 0;
double second = 0;
for (int i = 0; i < rounds; i++)
{
sw.Start();
for (int bar = 0; bar < timesToCreateString; bar++)
{
var foo = "Some text, " +
$"some other {bar}, " +
"end text.";
}
sw.Stop();
first += sw.ElapsedTicks;
sw.Reset();
sw.Start();
for (int bar = 0; bar < timesToCreateString; bar++)
{
var foo = $"Some text, " +
$"some other {bar}, " +
$"end text.";
}
sw.Stop();
second += sw.ElapsedTicks;
sw.Reset();
}
Console.WriteLine("Average first test: " + first / rounds);
Console.WriteLine("Average second test: " + second / rounds);
Console.ReadKey();
// program ran 3 times and results.
//Average first test: 54822.04
//Average second test: 55083.86
//Average first test: 54317.66
//Average second test: 54807.8
//Average first test: 49873.12
//Average second test: 48264.36
答案 2 :(得分:1)
看看IL:
第一个代码:
var bar = "a";
var foo = "b" + $"{bar}";
第一次IL:
IL_0000: nop
IL_0001: ldstr "a"
IL_0006: stloc.0 // bar
IL_0007: ldstr "b"
IL_000C: ldstr "{0}"
IL_0011: ldloc.0 // bar
IL_0012: call System.String.Format
IL_0017: call System.String.Concat
IL_001C: stloc.1 // foo
IL_001D: ret
第二个代码:
var bar = "a";
var foo = $"b" + $"{bar}";
第二次IL:
IL_0000: nop
IL_0001: ldstr "a"
IL_0006: stloc.0 // bar
IL_0007: ldstr "b"
IL_000C: ldstr "{0}"
IL_0011: ldloc.0 // bar
IL_0012: call System.String.Format
IL_0017: call System.String.Concat
IL_001C: stloc.1 // foo
IL_001D: ret
两个代码之间没有编译差异。
PS :( IL由Linqpad 5.22.02生成)。
答案 3 :(得分:1)
您可以选择自己喜欢的任何内容。确实$转换为string.format(参见https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/interpolated-strings),但编译器足够聪明,可以过滤掉未格式化的代码。