C# 为什么在空“中没有关于可能错误的空语句的警告;而";环

C# 为什么在空“中没有关于可能错误的空语句的警告;而";环,c#,visual-studio,visual-studio-2017,compiler-warnings,C#,Visual Studio,Visual Studio 2017,Compiler Warnings,有很多帖子,我知道这是怎么回事。例如,未使用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? 为什么不一致?没有不一致。CS0642并不是验证代码是否有意义,或者是否曾

有很多帖子,我知道这是怎么回事。例如,未使用
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?

为什么不一致?

没有不一致。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中也是如此

顺便说一句,如果是Eric Lippert的话,就不会有
在所有地方,它将是
{}

空语句功能是冗余的,很少需要,而且 容易出错,这为编译器团队实现 警告告诉你不要使用它。这项功能可能只是简单的 从C#1.0中删除。


接下来的一个问题是,为什么C#编译器没有明显地警告任何非平凡的条件,这些条件总是
true
false
,这是C编译器的一个相当常见的特性。编译器对总是
true
false
的表达式(如CS0464,“与'type'类型的null进行比较总是产生'false')有一些警告,但不是一般的警告。这背后可能有一个设计决定,我甚至可能看过Eric Lippert关于它的博客——或者我只是想象了一下。无论如何,没有得到警告与CS0642无关。

关于这一点,你也可以这样做:虽然(正确)关于计时器,但我认为警告是关于“x”,称之为“不一致”似乎是不真实的。您是否希望编译器具备
计时器
的领域知识?这是一个警告而不是错误的全部原因是因为编译器不确定。“为什么编译器不在总是正确的
条件下发出警告”(即“x”示例)是一个有效但独立的问题。CS0642实际上相当聪明,因为它似乎设计用于捕捉明显的印刷错误而不是语义错误:
while(x<3)不触发警告,但
while(x<3);{…}
。我猜
while(总是真实的条件)在有效代码中经常出现,因此被排除在外(在任何情况下,都需要进行不同类型的检查)。还要注意,
使用(…){}
也不会触发警告——空块在任何情况下都可以,因为您显然没有键入这些块。空块可能仍然是一个错误,但没有一个CS0642关心它。(这也解释了为什么我不记得在最近的记忆中见过它——我从来没有在可能出现块的地方使用过单独的
)。我知道没有任何原则性的一般理由来证明为什么C编译器没有检测到尽可能多的“总是真/总是假”条件。与特性工作相比,它并不是编译器团队的优先事项,所以它并没有完成。如果你认为它应该是一个优先事项,你可以在Roslyn github论坛上提到它。如果编译器对“表达式总是具有相同的值,但包含变量”和“转换太晚”这一更普遍的问题更聪明一些,我也会喜欢它。这些都是问题的共同来源;我一直看到“百分比=(双精度)(x/100);”,其中x是从0到100的整数,当然百分比总是0或1。
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
TextWriter x = null;
using (x) ;  // CS0642
    x.WriteLine();  // whoops, use of disposed object