Why assigning null in ternary operator fails: no implicit conversion between null and int?

前端 未结 5 2007
青春惊慌失措
青春惊慌失措 2020-12-11 16:08

This fails with a There is no implicit conversion between \'null\' and \'int\'

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


        
相关标签:
5条回答
  • 2020-12-11 16:12

    The Compiler tries to evaluate the expressions from left to right

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

    int64.parse method return a long value not a nullable long value. so there is no conversion between null and Int64.Parse( myOtherVar); So, try this one

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

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

    0 讨论(0)
  • 2020-12-11 16:29

    I am sure you meant to say:

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

    instead of

      myVar = value == 0 ? null : value;
    

    I liked the usage of the 'out' variable. Thanks.

    0 讨论(0)
  • 2020-12-11 16:32

    The compiler ignores the left-hand side when figuring out the type of the right-hand side. So when it tries to deduce the type of

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

    it does so without paying any attention to the fact the left-hand side is a long?. To determine the type of the right-hand side it notes that

    Int64.Parse(myOtherVar)
    

    is a long and now tries to see if null is or can be implicitly converted to a long. Since it can not, you get the error message that you see.

    From §7.14 of the C# specification:

    A conditional expression of the form b ? x : y....

    The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

    (1) If x has type X and y has type Y then

    a. If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

    b. If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.

    c. Otherwise, no expression type can be determined, and a compile-time error occurs.

    (2) If only one of x and y has a type, and both x and y, of areimplicitly convertible to that type, then that is the type of the conditional expression.

    (3) Otherwise, no expression type can be determined, and a compile-time error occurs.

    Note that we are in situation (2) where x is null and does not have a type and y is Int64.Parse(myOtherVar) and has type long. Note that x is not implicitly convertible to the type of y. Therefore both (1) and (2) fail above and we result in (3) which results in the compile-time error that inspired your question. Note the implicit conclusion from the above that the left-hand side does not play a role in determining the type of right-hand side.

    To rectify this replace

    Int64.Parse(myOtherVar)
    

    with

    (long?)Int64.Parse(myOtherVar)
    

    Now, the reason why

    myVar = null;
    

    is okay where myVar is declared as long? is because the compiler knows there is an implicit conversion from null to long?.

    Lastly, Int64.Parse will throw if myOtherVar can't be parsed to a long. Note that you are also performing the parse twice, which is unnecessary. A better pattern is

    long value;
    if(Int64.TryParse(myOtherVar, out value)) {
        myVar = value == 0 ? null : (long?)value;
    }
    else {
        // handle case where myOtherVar couldn't be parsed
    }
    
    0 讨论(0)
  • 2020-12-11 16:33

    This will work:

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

    ..for those who like short answers.

    0 讨论(0)
  • 2020-12-11 16:37

    Your operator usage is returning an Int64, not a nullable one, because of the last part of the ternary operator. It may work if you do instead:

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

    So that you are returning a long? instead, so the null doesn't need to be converted to Int64

    Also, you are converting the value twice in your code, unnecessarily (once to test, and once to get the value). Your code might be better thus:

    long? tempVar = Int64.Parse(myOtherVar);
    long? myVar = tempVar==0? null : tempVar;
    
    0 讨论(0)
提交回复
热议问题