在格式字符串的全文是静态的并且在编译时已知的情况下,丢失的格式字符串参数不应该是编译时错误,或者至少是警告吗?
ReSharper 捕捉到了这一点,但它只是一个带下划线的曲线。我的印象是这会触发一般的编译时错误:
string x = string.Format("soeuotnh {0}");
有什么方法可以触发此类错误的警告,而无需通过 FxCop 或其他方式运行我的代码?即使是 C/C++ 编译器也会针对如此明显的错误触发警告/错误(尽管它们通常不会检查类型安全)。
在格式字符串的全文是静态的并且在编译时已知的情况下,丢失的格式字符串参数不应该是编译时错误,或者至少是警告吗?
ReSharper 捕捉到了这一点,但它只是一个带下划线的曲线。我的印象是这会触发一般的编译时错误:
string x = string.Format("soeuotnh {0}");
有什么方法可以触发此类错误的警告,而无需通过 FxCop 或其他方式运行我的代码?即使是 C/C++ 编译器也会针对如此明显的错误触发警告/错误(尽管它们通常不会检查类型安全)。
这可能是一个警告,但它应该是吗?好吧,我想这取决于编译器团队,它不像String.Format
是 C#语言的一部分。
这不是 C;你没有调用未定义的行为或任何东西,该方法可以简单地处理丢失的参数,并且假设(我假设......)当它抛出异常时你会很快捕获它。没有什么“危险”的,这只是一个逻辑错误。
除了您提到的自动检测这种情况之外,我认为没有其他方法。至于为什么会发生这种情况,Format 方法与重载相匹配(String, params Object[])
,其参数在文档中定义如下:
public static string Format(
string format,
params Object[] args
)
format 类型:System.String
复合格式字符串(请参阅备注)。args 类型:System.Object[] 包含零个或多个要格式化的对象的对象数组。
由于params
定义了可变数量的参数(包括零个参数),这就是为什么没有抛出编译时异常的原因。
编辑:
由于编译器可以选择有效的重载,因此您不会收到编译时错误。所以这不再是编译器问题,最好的办法是使用代码质量工具 Resharper 来检测这种情况。
一些 C 编译器会解析格式字符串,因为格式字符串与参数不匹配会导致严重的崩溃错误——甚至更糟糕的是,安全错误。但是,在 C# 中,您只会在调用站点遇到异常,因此这并不重要。
编译器可以做到这一点,但这需要将代码识别string.Format
为特殊情况,并且(更糟糕的是)需要有人在 C# 编译器中编写格式字符串解析器。所有这些都是为了警告您每次执行时都会崩溃的代码。
这样做的一个大问题是,许多人在编译时将所有警告都打开并将警告作为错误,这意味着添加此警告将破坏他们的构建。任何人在其代码的黑暗角落中的一些错误格式字符串从未执行过,将突然无法构建他们的产品。这些人会抱怨。
正如已经说过的,这不是编译器要做或应该担心的事情。
在执行以下操作时,您希望编译器如何表现:
string format = "{0}";
List<string> parms = new List<string> { "Hello" };
if (DateTime.Now.Second % 2 == 0)
{
format += " {1}";
parms.Add("World");
}
Console.WriteLine(format, parms.ToArray());
Resharper针对这种情况显示警告:“格式化字符串中不存在参数”。
该方法的“格式”参数不是常数。所有不是常量的东西都不能在编译时检查。
它可以通过各种方法在运行时组合,甚至可以是用户输入...(恐怖!)
这就是为什么它不是编译时错误。
编辑:好的,如果它是一个常量表达式,可以对其进行分析并生成警告。但这里是Eric Lipert 对另一个有点适用的问题的回答:收益高于成本。
这是否是值得为 String.Format (可能还有其他字符串格式函数)花费特殊情况场景的真正好处……这是一个艰难的决定。
我已在 Microsoft Connect 上提交了考虑此功能的请求,因为我认为
归根结底,这是一种“可以,不可以,也许应该”的情况。我试图确保我无法在编译器(不是第三方软件)中设置任何东西以使其警告更具侵略性,或者如果有某种方式我可以更改我的代码以使其抛出异常(例如,将所有内容声明为 const),但事实证明(到目前为止)这是不可能的。无论 Visual Studio 团队对我在 MS Connect 上打开的问题的反应如何,事实仍然是编译器肯定可以在编译时捕获大量字符串格式异常,这将是一个好处......但它仍然存在VS 团队来确定它是否值得实施。