I'm writing a piece of code in c#6 and for some strange reason this works
var value = objectThatMayBeNull?.property;
but this doesn't:
int value = nullableInt?.Value;
By not works I mean I get a compile error saying Cannot resolve symbol 'Value'
.
Any idea why the null conditional operator ?.
isn't working?
I basically agree with the other answers. I was just hoping that the observed behavior could be backed up by some form of authoritative documentation.
Since I can't find the C# 6.0 specification anywhere (is it out yet?), the closest I found to "documentation" are the C# Language Design Notes for Feb 3, 2014. Assuming the information found in there still reflects the current state of affairs, here are the relevant parts that formally explain the observed behavior.
Applying that last rule to:
... the semantically equivalent expression becomes:
Clearly,
nullableInt.Value.Value
can't compile, and that's what you observed.As to why the design decision was made to apply that special rule to nullable types specifically, I think
dasblinkenlight
's answer covers that nicely, so I won't repeat it here.Additionally, I should mention that, even if, hypothetically, we didn't have this special rule for nullable types, and the expression
nullableInt?.Value
did compile and behave as you originally thought...still, the following statement from your question would be invalid and produce a compilation error:
The reason why it would still not work is because the type of the
nullableInt?.Value
expression would beint?
, notint
. So you would need to change the type of thevalue
variable toint?
.This is also formally covered in the C# Language Design Notes for Feb 3, 2014:
But if you would then be forced to write the following to make it compile:
... then it seems pretty pointless, and it wouldn't be any different from simply doing:
As others have pointed out, in your case, you probably meant to use the null-coalescing operator
??
all along, not the null-conditional operator?.
.The null conditional operator also unwraps the nullable variable. So after the "?." operator, the “Value” property is no longer needed.
I wrote a post that goes more into detail on how I came across this. In case you're wondering
http://www.ninjacrab.com/2016/09/11/c-how-the-null-conditional-operator-works-with-nullable-types/
int
doesn't have aValue
property.Consider:
Is equivalent to:
That makes no sense with
int
and hence not withint?
via?.
The old
GetValueOrDefault()
does though make sense withint?
.Or for that matter, since
?
has to return something nullable, simply:Simply because (based on sstan's answer above)
is evaluated by compiler like
and
like
when
nullableInt.Value.Value
isCannot resolve symbol 'Value'
syntax error!The reason for this is that accessing the value with a null conditional operator would be pointless:
x?.p
wherep
is a non-nullable value typeT
, the result is of typeT?
. By the same token, the result ofnullableInt?.Value
operation must be nullable.Nullable<T>
has a value, the result ofnullableInt?.Value
would be the same as the value itselfNullable<T>
does not have a value, the result would benull
, which is, again, the same as the value itself.Although it does not make sense to access
Value
with the?.
operator, it does make sense to access other properties of nullable value types. The operator works consistently with nullable value types and with reference types, so these two implementations produce identical behavior:In case of a nullable
struct
the operator lets you access a property of the underlying typePointStruct
, and it adds nullability to the result in the same way that it does for non-nullable properties of the reference typePointClass
.Okay, I have done some thinking and testing. This is what happens:
Gives this error message when compiling:
That means that
?
'converts' theint?
into the actualint
value. This is effectively the same as:The result is an integer, which doesn't have a
Value
, obviously.Okay, might this help?
No, that syntax isn't allowed.
So what then? Just keep using
.GetValueOrDefault()
for this case.