null
can represent any object-based datatype. You need to cast null
as a datatype so it know what you are talking about.
int? x = (value.HasValue) ? value.Value : (int?)null;
I know, it sounds a bit strange.
To answer the questions in the comments:
Why is it not implicit though?
Yeah, I get that. But why do I not have to cast it in a If Else block?
Let's walk through the code.
Your else
statement looks like this:
else x = null;
This means you are assigning the value of null
to x
. This is valid, because x
is a int?
, which takes nulls
.
The difference comes when you have the ternary operator. It says: "assign the value of the operator into x
". The question (and the reason for your error) is, what datatype is the result of the ternary operator?
From your code, you can't be sure, and the compiler throws its hands up.
int? x = (value.HasValue) ? value.Value : null;
// int? bool int ??
What datatype is null
? You are quick to say "well it's a int?
, because the other side is a int
and the result is a int?
". The problem is, what about the following:
string a = null;
bool? b = null;
SqlConnectionStringBuilder s = null;
This is also valid, which means null
can be used for any object-based datatype
. This is why you have to explicitly cast null
as the type you want to use, because it can be used for anything!
Another explanation (and possible more accurate):
You can't have an implicit cast between a nullable and a non-nullable value.
int
is not-nullable (it's a structure), where null
is. This is why in Habib's answer you can put the cast on either the left or right side.
The null propagation operator returns a value. And since you must have a variable on the left hand side of an assignment, and not a value, you cannot use it in this way.
Sure, you could make things shorter by using the tenary operator, but that, on the other hand, doesn't really help the readability aspect.
Joachim Isaksson's comment on your question shows a different approach that should work.
Best Answer
The problem occurs because the conditional operator doesn't look at how the value is used (assigned in this case) to determine the type of the expression -- just the true/false values. In this case, you have a
null
and anInt32
, and the type can not be determined (there are real reasons it can't just assumeNullable<Int32>
).If you really want to use it in this way, you must cast one of the values to
Nullable<Int32>
yourself, so C# can resolve the type:or