A simple class with a copy constructor, which calls another constructor:
public class Foo<TEnum> where TEnum : Enum
{
public Foo(TEnum myEnum)
{
MyEnum = myEnum;
}
public Foo(Foo<TEnum> foo) : this(foo.MyEnum) { }
public TEnum MyEnum { get; }
}
That would show warning:
warning CA1062: In externally visible method 'Foo{TEnum}.Foo(Foo{TEnum} foo)', validate parameter 'foo' is non-null before using it. If appropriate, throw an 'ArgumentNullException' when the argument is 'null'.
I ordinarily would do this:
public Foo(Foo<TEnum> foo)
: this(foo?.MyEnum ?? throw new ArgumentNullException(nameof(foo))) { }
But that doesn't compile:
'TEnum' cannot be made nullable.
Am I missing something obvious or is this a limitation of some sort?
(I prefer not to suppress that warning as it's important; I'd like to do the validation somehow.)
Answer
You should also constrain TEnum
to value types.
public class Foo<TEnum> where TEnum : struct, Enum
Then it can "be made nullable".
public Foo(Foo<TEnum> foo)
: this(foo?.MyEnum ?? throw new ArgumentNullException(nameof(foo))) { }
Without the struct
constraint, it is unknown whether TEnum
is a value type or reference type. TEnum
cannot be made nullable, because the nullable version of a type depends on whether it is a value type or reference type. If TEnum
is a reference type, the nullable version will just be the type itself. If it is a value type, the nullable version will be System.Nullable<TEnum>
.