代码之家  ›  专栏  ›  技术社区  ›  Leisen Chang

为什么!运算符在==false时工作,在这种情况下不是吗?

  •  0
  • Leisen Chang  · 技术社区  · 5 年前

    预期的工作如下:

    dynamic foo = GetFoo();
    
    if (foo != null)
    {
        if (foo is Foo i)
        {
            Console.WriteLine(i.Bar);
        }
    }
    

    但是,如果我将if语句组合起来,就像这样:

    if (foo != null && foo is Foo i)
    {
        Console.WriteLine(i.Bar);
    }
    

    然后我收到一个编译器警告

    Use of unassigned local variable 'i'

    有人能解释为什么会这样吗?

    0 回复  |  直到 6 年前
        1
  •  8
  •   Matthew Watson    6 年前

    事实上,这似乎不是编译器错误。

    它以前被报告为一个错误 here .

    但是,它已经被关闭,因为它不是一个bug。原因是因为C语言规范的这一部分(注:我这里是从用户那里引用的 gafter 在Github上-这不是我的原始内容):

    如果条件逻辑运算符的操作数具有编译时类型dynamic,则表达式是动态绑定的(动态绑定)。在这种情况下,表达式的编译时类型是动态的,下面描述的解析将在运行时使用具有编译时类型动态的操作数的运行时类型进行。

    具体来说,&运算不是编译时布尔短路运算,因为其右侧操作数的类型为动态。

    微妙的东西,正如大卫上面所说,另一个避免的原因 dynamic 如果可能的话!(我必须承认,我仍然不完全相信 一个bug,但那只是我不理解我想的一切…)

        2
  •  1
  •   UladzislaÅ­    6 年前

    好吧,我考虑过这个问题,看起来编译器的行为是非常正确的,即使没有 dynamic 价值观。

    不过,还需要一些奇怪的代码。

    首先,我们会超载 && 我们的接线员 Foo 类型。不能直接过载短路逻辑运算符,因此我们将过载 true , false & 分开。

    public static bool operator true(Foo x) => true;
    public static bool operator false(Foo x) => true;
    public static Foo operator &(Foo foo, Foo val) => new Foo();
    

    最初我们有一个表情 foo != null && foo is Foo i 在里面 if 阻止,现在我们要 && 从它到束缚到我们的超负荷。因此,我们将超载 != 操作员和 == 而且它们应该总是成对的。

    public static Foo operator !=(Foo val, Foo val2) => new Foo();  
    public static Foo operator ==(Foo val, Foo val2) => new Foo();
    

    暂时 foo != null 计算结果为 foo is Foo 计算结果为 bool 但是我们的 && 重载具有签名 (Foo, Foo) -仍然不匹配,将为隐式转换添加一个重载 布尔 .

    public static implicit operator Foo(bool val) => new Foo();
    

    这是密码 类型我们到目前为止

    class Foo
    {
        public static bool operator true(Foo x) => true;
        public static bool operator false(Foo x) => true;
        public static Foo operator &(Foo foo, Foo val) => new Foo();
    
        public static implicit operator Foo(bool val) => new Foo();
    
        public static Foo operator !=(Foo val, Foo val2) => new Foo();
        public static Foo operator ==(Foo val, Foo val2) => new Foo();
    }
    

    瞧!我们对这篇文章也有同样的错误。

     static void Main(string[] args)
     {
         Foo foo = GetFoo();
    
         if (foo != null && foo is Foo i)
         {
             // Use of unassigned local variable i
             // Local variable 'i' might not be initialized before accessing 
             Console.WriteLine(i);
         }
     }
    
     static Foo GetFoo() => new Foo();
    

    事实上,如果我们用 foo is string i 而不是 foo is Foo i , i 不会在运行时初始化,但我们将在内部 如果 块。

    由于 动态 涉及的值。 福!=空 动态 ,直到 foo 动态 所以这意味着 && 应该在运行时绑定,我们不能保证 将被初始化。

    看起来马修引用了Github发行的同样的话,但我个人从一开始就无法理解。