【发布时间】:2018-09-23 12:42:57
【问题描述】:
我发现了一些我认为无法访问且未被检测到的代码的情况。 编译器和 Visual Studio 都不会发出警告。
考虑这段代码:
enum Foo { A, B, C }
class Bar { public Foo type; }
static class Program
{
private static void Main()
{
var bar = new Bar { type = Foo.A };
if (bar.type == Foo.B)
{
Console.WriteLine("lol");
}
}
}
显然,程序不会打印出“lol”,因为 if 语句中的条件为假。 我不明白为什么不为无法访问的代码发出警告。 我唯一的假设是,如果您在多线程程序中存在竞争条件,那么这可能是可以实现的。这是正确的吗?
【问题讨论】:
-
运行时检查。
-
编译时检查可达性并不能涵盖所有内容。因此,您通常会在单元测试期间或通过手动运行程序来记录代码覆盖率。虽然竞争条件是一个有效的情况,但更有可能的是
Bar类修改了值本身。在您的示例中可能不是这种情况,但在现实世界的应用程序中肯定有可能。 -
这种分析需要编译器解决臭名昭著的停机问题。设计师明智地不要试图解决这个问题。
-
在很多情况下,编译器不会报告无法访问的代码。
int x = M(); if (x == 123.456) { /* unreachable */ }比较是合法的,因为x可以转换为double,无论x 的值是多少,比较总是为false。编译器不够聪明,无法推断出这一点,并且规范并不要求那么聪明。如果您习惯于编写无法访问的代码,那么养成使用代码覆盖工具的习惯。 -
顺便说一句,编译器曾经将
int x = M(); if (x * 0 != 0) { ... }中的结果视为不可达,推理任何int 乘以零为零,因此条件为假。虽然这个推理是正确的,但规范中找不到该规则,因此是我修复的编译器中的一个错误。从 C# 3.0 开始,编译器已根据规范正确地将if的结果视为不可达仅当条件为假且仅涉及常量表达式时。
标签: c# .net unreachable-code