C# 10 添加了对更好的字符串内插的支持,包括除字符串外还可以面向自定义“处理程序”。 StringBuilder 通过可接受自定义内插字符串处理程序的新重载 Append 和 AppendLine 来利用这一功能。 对这些方法的现有调用现在可能会开始绑定到新的重载。 一般情况下,行为相同,但性能有所提高。 例如,与其首先创建一个字符串后再将其追加,不如将内插字符串的各组件直接追加到生成器中。 但是,这可以更改用作格式项的对象评估顺序,这可以表现为行为差异。
以前的行为
在之前的版本中,对此项的调用:
stringBuilder.Append($"{a} {b}");
会编译为此项的等效项:
stringBuilder.Append(string.Format("{0} {1}", a, b));
这意味着 a
会计算,然后 b
计算,然后根据这些计算的结果创建一个字符串,然后将该字符串追加到生成器。
新行为
从 .NET 6 开始,对此项的调用:
stringBuilder.Append($"{a} {b}");
会编译为此项的等效项:
var handler = new StringBuilder.AppendInterpolatedStringHandler(1, 2, stringBuilder);
handler.AppendFormatted(a);
handler.AppendLiteral(" ");
handler.AppendFormatted(b);
stringBuilder.Append(ref handler);
这意味着 a
被评估并追加到构建器,然后 b
被评估并追加到构建器。
例如,a
或b
如果本身是构建器,如以下代码所示,新的求值顺序可能会导致运行时出现不同的行为。
stringBuilder.Append($"{a} {stringBuilder}");
已引入的版本
6.0 RC 1
破坏性变更的类型
此更改可能会影响 源兼容性。
更改原因
开发人员通常会将内插字符串 StringBuilder传递到其中,因为它比手动拆分字符串并为每个部分调用 StringBuilder.Append 更方便。 这些新重载可实现简洁的语法以及执行单独调用的大部分性能。
建议的措施
在大多数情况下,使用StringBuilder.Append和StringBuilder.AppendLine时,您不会注意到功能差异。 如果发现存在问题的差异,可以通过在内插字符串之前添加 (string)
强制转换来还原以前的行为。 例如:
stringBuilder.Append((string)$"{a} {b}")
但是,除非确实需要兼容,否则不建议这样做。