以下内容将在运行时引发异常:
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),但是:编译器对这个字符串中的内容一点也不感兴趣。