As noted, the type Nullable<T>
is a struct which encapsulates a T
and a flag which indicates whether it is valid. Because the implementers of .NET didn't see any usefulness to being able to have a type which could encapsulate a thing of any thing and indicate whether it was valid, they decided that they didn't want to allow Nullable<Nullable<T>>
[a decision I dislike, by the way], and rather than come up with a special constraint just for the generic parameter in Nullable<T>
, they decided that even though Nullable<T>
is a struct, it shouldn't satisfy a struct
type constraint.
Personally, I'd have rather seen Nullable<T>
either simply be an "ordinary" struct with exposed fields of type bool
and unconstrained T
, which could be used by e.g. Dictionary.TryGetValue
to return a value and indicate whether it was valid (regardless of whether TValue
was a class, a non-nullable struct, or a Nullable<T>
), or else have it be a class containing a T
. The value of being able to say someNullable != null
as a shortcut is minuscule compared to the confusion and complications it causes compared with someNullable.HasValue
. Still, .NET is what it is. Personally, I would suggest generally avoiding nullable types, since one can't do much of anything with a nullable type without copying out the value first. Such types also have some weird quirks with regard to thread safety (e.g. code that receives a Nullable<T>
and observes that HasValue
cannot safely assume that GetValueOrDefault
will return Default(T)
, even if nothing can possibly have modified the Nullable<T>
since it was received).