Reputation: 4406
Have you ever tried to use the Convert.ChangeType()
method to convert a value to a Nullable<T>
type? Awkwardly, it will throw an InvalidCastException
saying "Null object cannot be converted to a value type".
Try running this on your immediate window: ?System.Convert.ChangeType(null, typeof(int?))
For some obscure reason, Nullables are considered value types. For example, typeof(int?).IsValueType
returns true
.
For me, since Nullable<T>
accept null
, it's a class type, not a value type. Does anyone know why it would implemented differently?
Upvotes: 15
Views: 3624
Reputation: 113222
I just saw this question in the "related questions" list at Why Nullable<T> is a struct? and I think my answer there applies here too. The whole point of Nullable<T>
is to act like a value type in every regard except for the ability to take a null value.
The null of a null reference can be looked at in two ways. One is that it isn't referencing anything, another is that it has no meaningful value. These things are pretty much two different ways of saying the same thing, but they have different uses.
Nullable<T>
gives us the ability to say "this has no meaningful value" and to that extent it can have the same semantics as a null reference, but it is not like a reference in any other way. When null it's nullity is purely that "no meaningful value" null - not "doesn't refer to anything" and when not null it is holding a value, not referring to it.
(Aaronaught argues that this means a Nullable can't really contain null, while I disagree because at the level at which it uses it can have a semantic null, his point is worth considering in that even when "null" a Nullable is different to a reference - really our disagreement is a matter of which level of abstraction we choose to use).
Upvotes: 2
Reputation: 421968
System.Nullable<T>
is technically a structure, so it's a value type (the null
value for a Nullable<T>
is not exactly the same thing as a null reference. It's a boolean flag that denotes the lack of a value.) However, it's treated specially by the runtime and this makes it an awkward value type. First, it doesn't satisfy where T : struct
type constraint (it doesn't satisfy where T : class
either, for what it's worth). Second, it exhibits an interesting boxing behavior. Boxing a Nullable<T>
will result in:
null
reference, if the value is null
.A boxed value of the underlying type if it actually contains a value. That is, in the statements:
int? x = 2;
object y = x;
y
is not a boxed Nullable<int>
. It's simply a boxed int
. You can unbox any boxed value of type T
to Nullable<T>
(and T
, of course). Casting a null
reference to Nullable<T>
results in a null
value (as you might expect).
This special treatment by the runtime makes nullable types work more similar to the way null
works in reference types.
Upvotes: 32
Reputation: 234354
Nullable<T>
is a value type (it's a struct, see in the MSDN documentation), but there is an implicit conversion from null
to a Nullable<T>
without a value (x.HasValue == false
). There is also an implicit conversion from values of type T
to values of type Nullable<T>
.
Additionally all operators are lifted from the regular types to work directly with nullable types.
Upvotes: 12
Reputation: 498904
Nullable<T>
is implemented as a struct and structs are value types.
Upvotes: 1