【问题标题】:Why assigning null in ternary operator fails: no implicit conversion between null and int?为什么在三元运算符中分配 null 失败:null 和 int 之间没有隐式转换?
【发布时间】:2011-05-16 11:14:03
【问题描述】:

这失败了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);

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

【问题讨论】:

    标签: c# ternary-operator


    【解决方案1】:

    编译器在确定右侧的类型时会忽略左侧。所以当它试图推断出的类型时

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

    它没有注意到左侧是long?这一事实。为了确定右侧的类型,它指出

    Int64.Parse(myOtherVar)
    

    long,现在尝试查看null 是否或可以隐式转换为long。由于不能,您会收到您看到的错误消息。

    来自 C# 规范的第 7.14 节:

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

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

    (1) 如果x 的类型为X,而y 的类型为Y,则

    一个。如果存在从XY,但不存在从YX 的隐式转换(第6.1 节),则Y 是条件表达式的类型。

    b.如果存在从YX 的隐式转换(第6.1 节),但不存在从XY,则X 是条件表达式的类型。

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

    (2) 如果xy 中只有一个具有类型,并且xy 都可以隐式转换为该类型,那么这就是条件表达式的类型。

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

    请注意,我们处于情况 (2),其中 xnull 并且没有类型,yInt64.Parse(myOtherVar) 并且具有类型 long。请注意,x 不能隐式转换为 y 的类型。因此,(1)和(2)都在上面失败,我们导致(3)导致编译时错误,激发了你的问题。 请注意上面的隐含结论,左侧在确定右侧的类型方面没有作用。

    纠正这个替换

    Int64.Parse(myOtherVar)
    

    (long?)Int64.Parse(myOtherVar)
    

    现在,原因

    myVar = null;
    

    myVar 被声明为long? 是可以的,因为编译器知道存在从nulllong? 的隐式转换。

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

    long value;
    if(Int64.TryParse(myOtherVar, out value)) {
        myVar = value == 0 ? null : (long?)value;
    }
    else {
        // handle case where myOtherVar couldn't be parsed
    }
    

    【讨论】:

    • 奇怪的是,Int64.Parse(myOtherVar) == 0 ? (长?) null : Int64.Parse(myOtherVar);工作。
    • 如果在访问器中有类似于“值”的东西,那就太好了,您可以在 if 语句中创建一个临时变量。
    • @Dr. Zim:Int64.Parse(myOtherVar) == 0 ? (long?) null : Int64.Parse(myOtherVar); 有效,因为存在从longlong? 的隐式转换。因此,(long?)null 的类型为 long?Int64.Parse(myOtherVar) 的类型为 long,后者隐式转换为 long?,因此编译器将表达式键入为 long?
    【解决方案2】:

    由于三元运算符的最后一部分,您的运算符使用返回 Int64,而不是 nullable。如果你这样做,它可能会起作用:

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

    因此您返回的是long?,因此null 不需要转换为Int64

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

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

    【讨论】:

      【解决方案3】:

      我确定你的意思是:

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

      而不是

        myVar = value == 0 ? null : value;
      

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

      【讨论】:

        【解决方案4】:

        这将起作用:

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

        ..对于那些喜欢简短答案的人。

        【讨论】:

          【解决方案5】:

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

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

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

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


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

          【讨论】:

            猜你喜欢
            • 2015-07-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-22
            • 2021-05-31
            • 2016-06-24
            • 2023-03-17
            • 2010-11-19
            相关资源
            最近更新 更多