Why is Nullable<T> considered a struct and not a class?

c#, generics, nullable, type-constraints

Solution

`Nullable<T>` is a struct, as per the documentation. It simply isn't a class. It's a value type, which looks a bit like this in terms of fields:

public struct Nullable<T>
{
    private readonly T value;
    private readonly bool hasValue;
}

The `null` value for a `Nullable<T>` type isn't a null reference, it's just a value where the `hasValue` field is false.

Note that `Nullable<T>` doesn't satisfy a condition for a constraint of `where TFoo : struct` however, as that's actually a non-nullable value type constraint. Basically `Nullable<T>` doesn't satisfy either the `class` or the `struct` constraint. There's no constraint which does only allow for nullable types (reference or `Nullable<T>`).

Problem

I'm trying to define a generic class that takes any type that can be set to null: ``` public abstract class BundledValue_Classes<T> where T : class { private Tuple<T, object> _bundle= new Tuple<T, object>(); public T Value { get { return _bundle == null ? null : _bundle.Item1; } set { _bundle = new Tuple<T, object>(value, obj); } } //... ``` This works fine. I also want to create a derived class that can take any primitive type (int, double, etc), and simply resolve that into the same as the above class, but where the primitive is wrapped in a Nullable ``` public abstract class BundledValue_Structs<T> : BundledValue_Classes<T?> where T : struct { //... } ``` But for some reason, this doesn't work. I get the error: `The type 'T?' must be a reference type in order to use it as parameter 'T' in the generic type or method 'BundledValue_Classes<T>'` Is it clear what I'm trying to do here? I don't want to have to copy paste the contents of the whole `BundledValue_Classes<T>` class just to handle the case of a primitive wrapped in a `Nullable<T>`. Perhaps there's some way to set the type constraint on `BundledValue_Classes<T>` so that it will not only accept classes, but any type that can be assigned a null value (including `Nullable<T>` types, which appear to be the only exception to the rule.)

Original source

Related problems