This fails with a There is no implicit conversion between 'null' and 'int'
long? myVar = Int64.Parse( myOtherVar) == 0 ? null : Int64.Parse( myOtherVar);
However, this succeeds:
if( Int64.Parse( myOtherVar) == 0)
myVar = null;
else
myVar = Int64.Parse( myOtherVar);
Is there a way to make the ternary operator succeed?
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
}
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;
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.
This will work:
long? myVar = (long?)myOtherVar == 0 ? null : (long?)myOtherVar;
..for those who like short answers.
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);