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

Why is there no warning about a possible mistaken empty statement in an empty "while" loop?

篇关于 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

为什么不一致?

没有不一致。 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 决定,根本就没有 ;,到处都是 { }

The empty statement feature is redundant, rarely needed, and error-prone, and it creates work for the compiler team to implement a warning telling you not to use it. The feature could simply have been cut from C# 1.0. (Source.)

一个后续问题是为什么 C# 编译器没有明显努力警告任何总是 truefalse 的重要条件,这是一个相当普遍的特征C 编译器。编译器对始终为 truefalse(如 CS0464、"Comparing with null of type 'type' always produces 'false'")但不是一般表达式的表达式有 一些 警告。这背后可能有一个设计决定,我什至可能看过一次 Eric Lippert 的博客——或者我只是想象那个。无论如何,没有得到警告与CS0642无关。