Conditional Operator Assignment with Nullable<Value> Types

Conditional operator assignment with Nullable value types?

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 an Int32, and the type can not be determined (there are real reasons it can't just assume Nullable<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:

EmployeeNumber =
string.IsNullOrEmpty(employeeNumberTextBox.Text)
? (int?)null
: Convert.ToInt32(employeeNumberTextBox.Text),

or

EmployeeNumber =
string.IsNullOrEmpty(employeeNumberTextBox.Text)
? null
: (int?)Convert.ToInt32(employeeNumberTextBox.Text),

Nullable types and the ternary operator: why is `? 10 : null` forbidden?

The compiler first tries to evaluate the right-hand expression:

GetBoolValue() ? 10 : null

The 10 is an int literal (not int?) and null is, well, null. There's no implicit conversion between those two hence the error message.

If you change the right-hand expression to one of the following then it compiles because there is an implicit conversion between int? and null (#1) and between int and int? (#2, #3).

GetBoolValue() ? (int?)10 : null    // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3

Null Conditional Operator with method .Value from Nullable structure

The variable?.Member on a nullable type of a value type T actually translates to a function roughly like

if (variable.HasValue)
return variable.GetValueOrDefault().Member;
else
return null;

variable.GetValueOrDefault() is of the type T, not Nullable<T>. Only Nullable<T> has a member Value (unless it is your own struct that contains a member Value, but e.g. int from your code does not).

Conditional Operator ?: with Nullable type Casting

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.

Why doesn't the conditional operator correctly allow the use of null for assignment to nullable types?

This doesn't work because the compiler will not insert an implicit conversion on both sides at once, and null requires an implicit conversion to become a nullable type.

Instead, you can write

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
DateTime.Parse(TextBoxActualEndDate.Text) : new DateTime?();

This only requires one implicit conversion (DateTime to DateTime?).

Alternatively, you can cast either left side:

task.ActualEndDate = TextBoxActualEndDate.Text != "" ? 
(DateTime?)DateTime.Parse(TextBoxActualEndDate.Text) : null;

This also requires only one implicit conversion.

C# Null Conditional Operator alternative (conditional assignment)?

The behavior you are expecting:

(i.e. If refTypeInstance is null, then simply do nothing. If refTypeInstance is not null, then execute the statement)

Is not possible because of the way operators work. More specifically, you have a problem with operator precedence and how expression trees are formed based on that:

In the statement

(unit as RangeUnit).PreferredTarget = UnitType.Melee;

The assignment operator (=) would be in the root of the expression tree, with the left and the right expressions as branches.

A NullReferenceException would occur when the left hand is evaluated (before assignment). At this point the compiler has already started to evaluate the =. Since the dereference operator (.) will throw a NullReferenceException at runtime, it is safe for the compiler to just continue parsing the expression tree.

On the other hand if this statement would permitted:

(unit as RangeUnit)?.PreferredTarget = UnitType.Melee;

...the compiler would have to emit code to check whether the value of refTypeInstance is null. It could do that, but the problem is, what would the compiler do with the expression tree that it is currently going through? It can not simply go on like in the first example, because it would have to discard the = up the expression tree and the . down the tree. It would basically have to insert two alternatives of parsing the tree, one when the left of ?. is null and one when it isn't. That however would be an alteration of the control flow, which is definitely not what you expect from an operator.

Or to put it differently: when long as ?. just short-circuits the evaluation of operators down its branch of the expression tree, you would consider this an expected behavior. But in this case this would alter the behavior of a operator higher up in the expression tree, which you would definitely not expect.

C# 6.0 null-conditional operator in if statements

if items is null, then items?.Count is null, too.

and null == 0 is a comparison that results in false. so the if is happy.

but items?.Any() will also be null - and if(null) is invalid, because null is not a boolean, and cannot be converted to one.

so you simply have to provide a fallback boolean value:

if (items?.Any() ?? false) {

}

will do the trick



Related Topics



Leave a reply



Submit