tags:

views:

234

answers:

3

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?

+8  A: 

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.

Martinho Fernandes
Why the downvote? I am wrong? If so, please enlighten me.
Martinho Fernandes
I upvoted to cancel downvote. :)
Patrick Karcher
+2  A: 

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

Oded
But no struct can receive a `null` value. I believe that Nullables are different enough from structs to not be considered structs.
jpbochi
`Nullable<T>` can't receive a `null` value either, it just has an implicit conversion to and from `null`. You could implement this on any custom `struct`, if you so desired.
Aaronaught
@Aaronaught: you can do something *similar* with a custom struct, but a lot of the behavior of nullable types cannot be mimicked through code. Nullable values are not just a library solution. They get special support from the compiler (and the CLR too, I think).
Martinho Fernandes
+12  A: 

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.

Mehrdad Afshari
The strange boxing behavior takes a while to understand - but I'm glad it's the way it is; otherwise much of the value of `Nullable<T>` (which comes from value passing transparency) would be lost.
LBushkin
Actually, the boxing behavior was a change that happened late in the development cycle of .NET 2.0. In early betas, `Nullable<T>` was a simple structure. In practice when you actually use nullable types to store nonexistent values, I too feel this behavior is more natural.
Mehrdad Afshari
Great added info by the way
Nick