为什么字符串。如果不指定所有参数,格式编译成功?



以下内容将在运行时引发异常:

 string s = string.Format("{0} {1} {2} {3} {4}",1,2,3,4);

但它会成功构建。为什么?

超过 3 个参数的String.Format使用params语法,因此所有参数都像数组一样传递,没有运行时检查项目数是否与格式相对应:

public static string Format(string format, object arg0);
public static string Format(string format, object arg0, object arg1);
public static string Format(string format, object arg0, object arg1, object arg2);
public static string Format(string format, params object[] args);

在一般情况下,格式字符串不一定是字符串文本,编译器不可能知道是否提供了足够的参数。

在这种特定情况下,编译器可以知道,但是准确描述在哪些情况下应将其视为编译时错误的开销相当高,并且存在 C# 碎片的风险,其中某些 C# 代码使用一个编译器编译并使用另一个编译器失败。至少有三种不同的 C# 编译器在现实世界中使用,它们应该遵循相同的规范。即使在编译时已知问题的情况下,将其视为运行时错误也可能是最不坏的解决方案。

因为string.Format()采用超过 3 个参数的变量参数列表(params语法),并且编译器不会"查看"格式说明符字符串。

如果您安装了锐化器,它会将这些标记为错误,

编译器在这里的工作是解析适当的字符串。与提供的参数匹配的格式方法,将 I 考虑适用的方法组、签名、转换运算符等 - 并生成适当的 IL 来实现这一点。编译器不关心字符串中的内容。语言规范没有提到string.Format,或任何碰巧与之相关的{n}等规则。对于编译器来说,它只是馈送到ldstr的数据。

有一些工具可以发现这一点(例如,resharper),但是:编译器对这个字符串中的内容一点也不感兴趣。

最新更新