在c# 6中声明使用字符串插值的长字符串
本文关键字:字符串 插值 声明 | 更新日期: 2023-09-27 18:10:32
我通常将长字符串连接起来:
Log.Debug("I am a long string. So long that I must " +
"be on multiple lines to be feasible.");
这是非常有效的,因为编译器处理字符串字面值的连接。我也认为这是处理这个问题最干净的方法(这里权衡了选项)。
此方法在String.Format
:
Log.Debug(String.Format("Must resize {0} x {1} image " +
"to {2} x {3} for reasons.", image.Width, image.Height,
resizedImage.Width, resizedImage.Height));
然而,我现在希望在这些情况下不再使用String.Format
,因为c# 6的字符串插值更具可读性。
我的问题是如果编译器可以以某种方式优化像
这样的东西Log.Debug($"Must resize {image.Width} x {image.Height} image " +
$"to {resizedImage.Width} x {resizedImage.Height} for reasons.");
到上面的String.Format
等价,或者如果有一个替代的方法,我可以使用,不会降低效率(由于不必要的连接),同时也保持我的代码整洁的结构(按照上面的链接提出的点)。
程序:
var name = "Bobby Tables";
var age = 8;
String msg = $"I'm {name} and" +
$" I'm {age} years old";
被编译,就好像你写了:
var name = "Bobby Tables";
var age = 8;
String msg = String.Concat(String.Format("I'm {0} and", name),
String.Format(" I'm {0} years old", age));
您看到了摆脱Concat
的困难—编译器已经重新编写了我们的插值文字,以使用String.Format
期望的索引格式化器,但是每个字符串必须从0开始为其参数编号。天真地将它们连接起来会导致它们都插入name
。为了正确解决这个问题,必须在$
解析器的调用之间维护状态,以便将第二个字符串重新格式化为" I'm {1} years old"
。或者,编译器可以尝试应用与字符串字面值连接相同的分析。我认为这将是一个合法的优化,即使字符串插值可能有副作用,但我不会感到惊讶,如果有一个角落的情况下,插补字符串连接改变程序的行为。这两种听起来都不可能,特别是考虑到逻辑已经存在,可以检测字符串字面量的类似条件,但是我可以理解为什么这个特性没有进入第一个版本。
也许它不像+
那样可读,但无论如何,这是可能的。你只需要在{
和}
之间换行:
Log.Debug($@"Must resize {image.Width} x {image.Height} image to {
resizedImage.Width} x {resizedImage.Height} for reasons.");
SO的着色脚本不能很好地处理这种语法,但c#编译器可以;-)
在HTML中使用此字符串的特殊情况下(或使用任何解析器进行解析,其中多个空白无关紧要),我可以建议您使用@$""
字符串(逐字插入字符串),例如:
$@"some veeeeeeeeeeery long string {foo}
whatever {bar}"
c# 6.0中:
var planetName = "Bob";
var myName = "Ford";
var formattedStr = $"Hello planet {planetName}, my name is {myName}!";
// formattedStr should be "Hello planet Bob, my name is Ford!"
然后连接stringbuilder:
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(formattedStr);
// Then add the strings you need
向stringbuilder添加更多字符串.....