Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
声明在C#6中使用字符串插值的长字符串_C#_Code Formatting - Fatal编程技术网

声明在C#6中使用字符串插值的长字符串

声明在C#6中使用字符串插值的长字符串,c#,code-formatting,C#,Code Formatting,我通常通过连接长字符串来包装它们: 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

我通常通过连接长字符串来包装它们:

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.");
或者如果有一种替代方法,我可以使用它,它不会降低效率(由于不必要的连接),同时保持代码的干净结构(根据上面链接中提出的要点)。

在c#6.0中:

然后与stringbuilder连接:

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.Append(formattedStr);
// Then add the strings you need 
将更多字符串附加到stringbuilder…..

此程序:

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
。为了正确地解决这个问题,必须在调用
$
解析器之间维护状态,以便将第二个字符串重新格式化为
“我{1}岁”
。或者,编译器可以尝试应用与字符串文本串联相同的分析。我认为这将是一个合法的优化,尽管字符串插值可能会有副作用,但如果结果是有一个角落的情况下,插值字符串串联改变了程序的行为,我不会感到惊讶。这两种方法听起来都不可能,特别是考虑到逻辑已经存在,可以检测字符串文本的类似情况,但是我可以理解为什么这个特性没有进入第一个版本


我会以您认为最干净、可读性最好的方式编写代码,并且不担心微效率低下,除非它们被证明是一个问题。关于代码主要是供人类理解的这句老话在这里仍然适用。

在HTML中使用此字符串的特殊情况下(或使用多个空格不重要的任何解析器进行解析),我建议您使用
@$”
字符串(逐字插入字符串),例如:


也许它不像
+
那样可读,但无论如何,它是可能的。您只需在
{
}
之间划一条线:

Log.Debug($@"Must resize {image.Width} x {image.Height} image to {
    resizedImage.Width} x {resizedImage.Height} for reasons.");

SO的着色脚本不能很好地处理这种语法,但C#编译器可以;-)

我看不出它与使用
String.Format
有什么不同的原因。好吧,我在LINQPad中测试过它,当使用C#6的字符串插值时,它肯定会执行一个串联(显式使用
String.Format
时不会发生这种情况)。我问的主要是希望有一种替代方法,编译器选项等等。我很惊讶格式字符串没有被视为编译时常量。你可以使用逐字插入字符串来代替(
$@…
)我认为整个“字符串是不可变的,不要连接它们”的智慧已经失控了。与计算中的任何“规则”一样,这个规则也有很多例外。只有在尝试进行实时(或接近实时)处理时(由于GC的不可预测性,您可能不应该在C#中进行处理),或者如果您正在进行几十次(更现实地说是数百次)的连接时,才会出现问题。将五个字符串串联在一起会在其他所有事情的噪音中丢失。我不会担心这一点,也不会在可读代码方面出错。我不认为这比仅仅使用操作符
+
更干净,它将在IL中使用单个
Concat
调用(与
StringBuilder
一样高效,但可读性更强)。此外,您的代码仍然存在前面提到的问题,即不必要的串联和使用多个
String.Format
调用,如果使用单个字符串,则不会出现这种情况。与“+”相比,StringBuilder在使用多个字符串时具有更好的性能。在本例中不一定如此,其中字符串在编译时已知。它被转换为一个
String.Concat
调用。使用
StringBuilder
的主要原因是避免在重复连接(特别是在循环中连接)时不必要地创建对象。但在这里,我们讨论的是一个典型的相当小的字符串数量,恰好太长,无法干净地换行。另请参见。这似乎只是一个问题,因为编译器没有意识到
$“{foo}”+$“{bar}”
$“{foo}{bar}”
相同。如果它可以先删除连接(在编译时),那么这种优化似乎是有意义的。虽然是的,但目前似乎不可能(需要编译器支持)。我正在使用临时的解决方法,就是不打断我的线路,让VS做软线路包装。这是一个有趣的方法,我没有想到。我喜欢这样,因为我们处于大括号之间,我们可以在不影响字符串的情况下使用空格。我喜欢逐字字符串可以跨行拆分,但必须将其一直向左对齐,这会让我很痛苦,所以我永远不会这样做。
$@"some veeeeeeeeeeery long string {foo} 
whatever {bar}"
Log.Debug($@"Must resize {image.Width} x {image.Height} image to {
    resizedImage.Width} x {resizedImage.Height} for reasons.");