为什么在空的“ while”循环中没有关于空语句可能错误的警告?

时间:2018-08-08 14:08:33

标签: c# visual-studio visual-studio-2017 compiler-warnings

关于compiler warning CS0642: "Possible mistaken empty statement"的帖子有,我了解其中的全部内容。例如,没有使用FileStream实例f,所以可能是一个错误:

using (var f = File.OpenRead("f.txt")) ; // Possible mistaken empty statement

但是,即使没有机会while等于或大于x,该3语句也不会发出警告。为什么?

int x = 1;
while (x < 3) ; // why no warning?

在此示例中,出现了警告,但Timer实例t实际上可以做某事,即触发回调:

using (var t = new Timer((x) => Debug.Print("This"), null, 500, 500)) ; // warning

为什么不一致?

1 个答案:

答案 0 :(得分:3)

没有不一致。 CS0642并不是要验证您的代码是否有意义或曾经执行过,它只是旨在捕获可能表示错误的某些语法模式。比较:

int x = 1;
while (x < 3) {}   // no warning
while (x < 3); {}  // CS0642
if (x < 3) ;       // CS0642
using (new object() as IDisposable) ;  // CS0642
using (new object() as IDisposable) {} // no warning
for (; x < 3 ;) ;  // empty statement *and* condition is always true, still no warning

用单个;而不是{ }编写空循环是程序员带来的一个普遍的C习惯用法(无论好坏);使这些总是触发CS0642可能会产生太多的误报。 using从来都不是C的习惯用法,因此强制将空块始终写为{ }似乎是合理的。当然,在某些情况下,您可能会出错:

TextWriter x = null;
using (x) ;  // CS0642
    x.WriteLine();  // whoops, use of disposed object

诚然,这不是一种可能的模式,即使将单个语句包装在块中也是一种好习惯,即使在C语言中也是如此。

顺便说一句,如果取决于埃里克·利珀特(Eric Lippert),根本就不会有;,到处都是{ }

  

空语句功能是多余的,很少需要,并且   容易出错,并且为编译器团队实现实现   警告告诉您不要使用它。该功能可能只是   从C#1.0中删除。   (Source.)

一个后续问题是,为什么C#编译器没有做出明显的努力来警告总是truefalse的任何非平凡条件,这是C编译器的一个相当普遍的功能。编译器对于始终为truefalse的表达式具有 some 警告(例如CS0464,“与类型为'type'的null进行比较始终会生成'false'”),但不是一般的。这背后可能有一个设计决定,我什至可能曾经见过Eric Lippert博客有关它的报道,或者也许我只是想象中的那样。无论如何,没有任何警告与CS0642无关。