c# - 为什么这段代码不可达?




.net unreachable-code (3)

C#规范说,

如果if语句可以访问且布尔表达式没有常量值false,则可以访问if语句的第一个嵌入语句。

并且,关于常数表达式

常量表达式必须是null文字或具有以下类型之一的值:sbyte,byte,short,ushort,int,uint,long,ulong,char,float,double,decimal,bool,object,string或any枚举类型。

在常量表达式中只允许以下构造:

  • 文字(包括null文字)。
  • 对类和结构类型的const成员的引用。
  • 引用枚举类型的成员。
  • 对const参数或局部变量的引用
  • 带括号的子表达式,它们本身是常量表达式。
  • 如果目标类型是上面列出的类型之一,则转换表达式。 选中和未选中的表达式
  • 默认值表达式
  • 预定义的+!~一元运算符。
  • 预定义的+*/%<<>>& ,|, ^&&||==!=<><=>=二元运算符,前提是每个操作数都是上面列出的类型。
  • ?:条件运算符。

成员访问表达式不在此列表中,因此布尔表达式不是常量。 因此if块的主体是可达的。

我发现了一个案例,我有一些我认为无法访问且未被检测到的代码。 编译器和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语句中的条件为false。 我不明白为什么没有为无法访问的代码发出警告。 我唯一的假设是,如果你在多线程程序中遇到竞争条件,那么这可能是可以达到的。 它是否正确?


因为在编译时不能做出这样的保证。 考虑这个替代Bar类

class Bar
{
   Random random = new Random();
   Array Foos = Enum.GetValues(typeof(Foo));

    private Foo _type;
    public Foo type
    {
        get { return _type; }
        set
        {
            _type = (Foo)Foos.GetValue(random.Next(3));
        }
    }
}

请注意,“可达”是在功能级别定义的。 即使在安全的情况下,也不允许到达正在测试的功能之外。


静态分析只能做很多事情,如果能证明代码无法更改,它只会将代码标记为无法访问。 在您的代码中, Bar内部发生的事情超出了方法流程的范围,无法进行静态推理。 如果Bar的构造函数启动一个将type值设置回B的线程怎么办? 编译器无法知道它,因为Bar的内部结构也没有作用于该方法。

如果您的代码正在检查局部变量的值,那么编译器可以知道它是否无法更改。 但事实并非如此。





unreachable-code