jpbochi
jpbochi

Reputation: 4406

Why are Nullable<T> considered a value type?

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

Answers (4)

Jon Hanna
Jon Hanna

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

Mehrdad Afshari
Mehrdad Afshari

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:

  • A 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

R. Martinho Fernandes
R. Martinho Fernandes

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

Oded
Oded

Reputation: 498904

Nullable<T> is implemented as a struct and structs are value types.

Upvotes: 1

Related Questions