代码之家  ›  专栏  ›  技术社区  ›  Zachary Scott

为什么在三元运算符中分配空值失败:空值和int之间没有隐式转换?

  •  11
  • Zachary Scott  · 技术社区  · 14 年前

    这失败了 There is no implicit conversion between 'null' and 'int'

    long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);
    

    然而,这成功了:

    if( Int64.Parse( myOtherVar) == 0)
        myVar = null;
    else
        myVar = Int64.Parse( myOtherVar);
    

    有没有办法让三元运算符成功?

    5 回复  |  直到 9 年前
        1
  •  25
  •   jason    14 年前

    当计算出右侧的类型时,编译器忽略左侧。所以当它试图推断

    Int64.Parse(myOtherVar) == 0 ? null : Int64.Parse(myOtherVar)
    

    这样做时,不需要注意左侧是一个 long? . 为了确定右侧的类型,它注意到

    Int64.Parse(myOtherVar)
    

    是一个 long 现在试着看看 null 是或可以隐式转换为 长的 . 因为它不能,所以您会收到您看到的错误消息。

    根据C规范第7.14条:

    形式的条件表达式 b ? x : y

    第二和第三个操作数, x y ,的 ?: 运算符控制条件表达式的类型。

    (1)如果 X 具有类型 X Y 具有类型 Y 然后

    a.如果隐式转换(_§6.1)存在于 X Y ,但不是来自 Y X 然后 Y 是条件表达式的类型。

    b.如果隐式转换(_§6.1)存在于 Y X ,但不是来自 X Y 然后 X 是条件表达式的类型。

    c.否则,无法确定表达式类型,会出现编译时错误。

    (2)如果只有一个 X Y 有一个类型,并且两者都有 X Y ,的类型可隐式转换为该类型,则该类型是条件表达式的类型。

    (3)否则,无法确定表达式类型,会出现编译时错误。

    请注意,我们的处境(2)是 X 无效的 并且没有类型和 Y Int64.Parse(myOtherVar) 并且有类型 长的 . 注意 X 不能隐式转换为 Y . 因此,上面的(1)和(2)都失败了,我们导致了(3),这导致了激发您问题的编译时错误。 请注意上面的隐含结论,即左侧在确定右侧类型时不起作用。

    要纠正这个问题,请更换

    Int64.Parse(myothervar)
    

    具有

    (long?)Int64.Parse(myOtherVar)
    

    现在,为什么

    myVar = null;
    

    哪里可以 myVar 声明为 长? 因为编译器知道 无效的 长? .

    最后, Int64.Parse 如果 myOtherVar 无法解析为 长的 . 注意,您还执行了两次解析,这是不必要的。更好的模式是

    long value;
    if(Int64.TryParse(myOtherVar, out value)) {
        myVar = value == 0 ? null : (long?)value;
    }
    else {
        // handle case where myOtherVar couldn't be parsed
    }
    
        2
  •  2
  •   Andrew Barber Eric Lafortune    14 年前

    您的操作员使用返回 Int64 ,不是 nullable 一,因为三元运算符的最后一部分。如果您改为这样做,它可能会工作:

    long? myVar = Int64.Parse( myOtherVar) == 0 ? null :
       (long?)Int64.Parse( myOtherVar);
    

    所以你要返回 long? 相反,所以 null 不需要转换为 英特64

    另外,您在代码中转换值两次,这是不必要的(一次转换为测试,一次转换为获取值)。您的代码可能更好,因此:

    long? tempVar = Int64.Parse(myOtherVar);
    long? myVar = tempVar==0? null : tempVar;
    
        3
  •  2
  •   Prasanna K Rao    14 年前

    我相信你是想说:

      myVar = value == 0 ? null : (long?)value;
    

    而不是

      myVar = value == 0 ? null : value;
    

    我喜欢“out”变量的用法。 谢谢。

        4
  •  0
  •   RayLoveless    9 年前

    这将起作用:

    long? myVar = (long?)myOtherVar == 0 ? null : (long?)myOtherVar;
    

    …对于那些喜欢简短回答的人。

        5
  •  0
  •   Shahid Raees PMP    9 年前

    编译器试图从左到右计算表达式

    long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);
    

    int64.parse 方法返回 long 值不是 nullable 长值。所以没有转换 null Int64.Parse( myOtherVar); 所以,试试这个

    long? myVar = Int64.Parse(myOtherVar) == 0 ? (long?) null : Int64.Parse(myOtherVar);
    


    long? myVar = Int64.Parse(myOtherVar) == 0 ? null : (long?) Int64.Parse(myOtherVar);