Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
416 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...