I have a parser that render text files into a datamodel. Some fields are optional, which are to be represented as null in the model.
However, a strange behavior is giving me a headache. When I handle nullable concretely, it behaves as expected.
Foo? a = null;
...works just fine.
Foo? b = default(Foo?);
...works also just fine. b is null.
However, whenever I wrap this inside a generic class, it seems that it has a difficulty treating the generic type parameter in the same way.
void Main()
{
Foo? is_null = null;
Foo? is_also_null = default (Foo?);
Foo? does_not_work = FooClass.GetNull<Foo>();
Foo? is_not_null = FooClass.GetDefault<Foo>(); // Should be null, AFAICT, but isn't,
}
public static class FooClass
{
public static T? GetNull<T>() where T:System.Enum
{
return null; //Compile error: CS0403 Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
}
public static T? GetDefault<T>() where T : System.Enum
{
return default(T?); // Why does this not return null? Shouldn't this be the same as default(Foo?) ?
}
}
public enum Foo
{
one,two,three
}
What am I doing wrong? Or what am I missing here?
CodePudding user response:
enum constraints basically: don't work as you expect; the T : Enum
doesn't mean it is treating it as a primitive - it is treating it as a boxed value (object) instead, that happens to be a sub-type of the Enum
type (or Enum
itself!). Emphasis: keep in mind that you could have used GetDefault<Enum>
here.
The T?
won't even compile without a compiler that supports Nullable Reference Types, and with NRT support and NRTs disabled: it will give you a CS8632 warning; this means that T?
here refers to NRTs, and not Nullable<T>
. You can fix this by adding the T : struct, Enum
, but without that: default(T?)
is just the same thing as default(T)
(because the ?
for NRTs doesn't change the type semantics - just whether we expect nulls or not), and default(T)
is the zero enum.