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

I am trying to define a generic class that accepts 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); } } //... 

It works great. I also want to create a derived class that can take any primitive type (int, double, etc.) and just allow it the same way as above, but where the primitive is wrapped in Nullable

 public abstract class BundledValue_Structs<T> : BundledValue_Classes<T?> where T : struct { //... } 

But for some reason this does not work. I get an 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>' 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 doing here? I do not want to copy the contents of the entire class BundledValue_Classes<T> only to handle the example primitive wrapped in Nullable<T> .

Perhaps there is a way to set the type restriction on BundledValue_Classes<T> so that it not only BundledValue_Classes<T> classes, but also any type that can be assigned null (including Nullable<T> ), which, apparently, are the only exception to the rule .)

+8
generics c # nullable type-constraints
source share
2 answers

Nullable<T> is a structure as per the documentation . This is just not a class. This is a value type that 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 the Nullable<T> not a null reference, it is just a value in which the hasValue field is false.

Note that Nullable<T> does not satisfy the where TFoo : struct constraint, all the more so as it is a constraint of a fuzzy type value. In principle, Nullable<T> satisfies neither the class constraint nor the struct . There is no restriction that allows only types with a null value (reference or Nullable<T> ).

+13
source share

As noted, the Nullable<T> is a structure that encapsulates a T and a flag that indicates whether it is valid. Since the .NET developers did not see any benefit in having a type that could encapsulate any thing and indicate whether it is valid, they decided that they did not want to allow Nullable<Nullable<T>> [solution I don’t like it, by the way], and instead of coming up with a special restriction only for the general parameter in Nullable<T> , they decided that even if Nullable<T> is a structure, it should not satisfy a condition like struct .

Personally, I would rather see a Nullable<T> or just a "normal" structure with open fields like bool and unconstrained T , which could be used, for example. Dictionary.TryGetValue to return a value and indicate whether it was valid (regardless of whether the TValue class, a non-empty structure, or a Nullable<T> ), or is it a class containing T A value indicating someNullable != null as a shortcut is negligible compared to the confusion and complexity it causes compared to someNullable.HasValue . However, .NET is what it is. Personally, I would suggest, generally speaking, to avoid types with a null value, since nothing can be done with a null type without first copying the value. These types also have some strange quirks regarding thread safety (for example, code that receives Nullable<T> , and notices that HasValue cannot safely assume that GetValueOrDefault will return Default(T) , even if nothing can change the value of Nullable<T> , since it was received).

0
source share

All Articles