【问题标题】:Why is there no warning about a possible mistaken empty statement in an empty "while" loop?为什么在空的“while”循环中没有关于可能错误的空语句的警告?
【发布时间】:2018-08-08 14:08:32
【问题描述】:

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

为什么不一致?

【问题讨论】:

  • 关于while,也可以这样做:while(true)
  • 关于计时器,我认为警告是关于'x'
  • 将此称为“不一致”似乎是不诚实的。您是否希望编译器具有Timer 的领域知识?这是一个警告而不是错误的全部原因是因为编译器不确定。 “为什么编译器不对始终为真的while 条件发出警告”(即“x”示例)是一个有效但独立的问题。
  • CS0642 实际上非常聪明,因为它似乎旨在捕捉明显的 typographical 错误而不是 semantic 错误:while (x &lt; 3) ; 不会触发警告,但while (x &lt; 3); { ... } 确实。我猜while (always-true-condition) ; 经常出现在有效代码中,以至于它被排除在外(无论如何,它需要进行不同类型的检查)。
  • 还要注意using (...) {} 也不会触发警告——空的blocks 在任何情况下都可以,因为你显然没有错别字。空块可能仍然是一个错误,但 CS0642 不在乎。 (这也解释了为什么我不记得在最近的记忆中见过它——我从不在会出现阻塞的地方使用单独的;。)

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


【解决方案1】:

没有不一致。 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 的表达式,编译器有一些 警告(如CS0464,“与'type' 类型的null 比较总是产生'false'”)但不是一般的警告。这背后可能有一个设计决定,我什至可能曾经看过 Eric Lippert 的博客——或者我只是想象那个。无论如何,没有收到警告与 CS0642 无关。

【讨论】:

  • 我知道为什么 C# 编译器没有检测到尽可能多的“始终为真/始终为假”条件是没有原则的一般原因。与功能工作相比,它根本不是编译器团队的高优先级,因此它没有完成。如果您认为它应该是优先事项,您可以在 Roslyn github 论坛上提及它。
  • 如果编译器对“表达式总是具有相同的值但涉及变量”和“转换为时已晚”的更普遍的问题更聪明,我也会喜欢它。这些是关于 SO 的常见问题来源;我一直看到“百分比 = (double)(x / 100);”其中 x 是从 0 到 100 的整数,当然百分比始终为零或一。
猜你喜欢
  • 2022-12-17
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多