不应该遗漏格式字符串参数是编译时错误?

时间:2012-04-17 16:29:23

标签: c# string-formatting

如果格式字符串的全文是静态的并且在编译时是已知的,那么丢失的格式字符串参数不应该是编译时错误,或者至少是警告吗?

ReSharper抓住了这个,但它只是一个带下划线的波浪形。我的印象是这会引发一般的编译时错误:

string x = string.Format("soeuotnh {0}");

有没有办法在不通过FxCop或其他东西运行我的代码的情况下触发此类错误的警告?即使是C / C ++编译器也会为这样一个明显的错误触发警告/错误(尽管它们通常不会检查类型安全性)。

7 个答案:

答案 0 :(得分:2)

可以是一个警告,但应该它?嗯,这取决于我想的编译器团队,它不像String.Format是C#语言的一部分

这不是C;你没有调用未定义的行为或任何东西,该方法可以简单地处理缺少的参数,并且假设是(我假设...),当它抛出异常时你会很快捕获它。它没什么“危险”,只是一个逻辑错误。

答案 1 :(得分:2)

除了你提到的自动检测这种情况之外,我认为没有任何办法。至于为什么会发生这种情况,Format方法与(String, params Object[])重载匹配,参数为defined in the documentation,如下所示:

public static string Format(
    string format,
    params Object[] args
)
  

格式   类型:System.String
  复合格式字符串(请参阅备注)。

     

ARGS   类型:System.Object []   包含或更多要格式化的对象的对象数组。

由于params定义了可变数量的参数(包括零参数),因此不会抛出编译时异常。

修改

由于编译器有一个有效的重载选择,因此不会出现编译时错误。因此,这不再成为编译器问题,最好的办法是使用Resharper(一种代码质量工具)来检测这种情况。

答案 2 :(得分:0)

某些C编译器将解析格式字符串,因为格式字符串与参数不匹配会导致严重的崩溃错误 - 甚至更糟的是安全漏洞。但是,在C#中,您只是在呼叫站点获得异常,因此它并不重要。

编译器可以这样做,但这需要代码将string.Format识别为特殊情况,并且(更糟糕的是)需要有人在C#编译器中编写格式字符串解析器。所有这些都可以警告你每次执行时会崩溃的代码。

这个问题的一大问题是,许多人将所有警告和警告编译为错误,这意味着添加此警告将破坏其构建。任何在代码的黑暗角落中有一些不良格式字符串的人都会突然无法构建他们的产品。这些人会抱怨。

答案 3 :(得分:0)

正如已经说过的,这不是编译器所做或应该担心的事情。

在执行以下操作时,您期望编译器的行为如何:

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());

答案 4 :(得分:0)

Resharper显示此情况的警告:“格式化字符串中不存在的参数”。

答案 5 :(得分:-1)

方法的“format”参数不是常量。在编译时无法检查所有非常量的内容。

它可以通过各种方法在运行时编写,甚至可以是用户输入...(恐怖!)

这就是为什么它不是编译时错误。

编辑:好的,如果它是一个常量表达式,则可以进行分析并生成警告。但这里有the answer from Eric Lipert on a different question有点适用:有一个好处超过成本。

这是否值得花费String.Format(以及可能的其他字符串格式函数)的特殊情况,这是一个真正的好处......是一个艰难的调用。

答案 6 :(得分:-2)

我已经在Microsoft Connect上提交了此功能的a request for consideration,因为我觉得

  • 答案说“人们更喜欢他们的代码编译并在运行时失败,如果它是一个不是很热的代码路径”,这只是荒谬的,在非解释语言中没有位置,特别是没有明确定义的强类型语言像C#一样重视类型安全。
  • 答案说编译器在物理上无法(在编译时)推断格式字符串和参数数组也是不正确的。是的,有些时候编译器无法在编译时推断出一个或另一个(或两者),并且没有什么可以做的,但很多时候,它有完整的信息可供使用。
  • 答案说这完全不是编译器的工作只是因为规范没有提到对这种行为发出警告而忽略了规范是编译器应该实现的最小值,并且编译器是免费的这一事实(并且确实在很大程度上),只要它与规范没有冲突,就超越它。
  • 答案说C编译器不这样做也是完全错误的 - 我有posted examples otherwise
  • 答案说我发布的代码示例在运行时没有抛出异常是明显错误的(尽管大多数已经编辑过了)。

在一天结束时,它是“是的,它可以,不,它没有,也许它应该”的情况。我试图确保没有我可以在编译器(而不是第三方软件)中设置的东西,以使其警告更具侵略性,或者是否有某种方式我可以更改我的代码使它抛出异常(例如,将所有内容声明为const),但事实证明(到目前为止)这是不可能的。无论Visual Studio团队对我在MS Connect上打开的问题做出的响应如何,事实上编译器当然可以在编译时捕获大量的字符串格式化异常,它是一个好处......但是VS团队仍然需要确定它是否值得实施。