Validation when one constructor calls another with enum in C#

Validation when one constructor calls another with enum in C#
typescript
Ethan Jackson

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>.

Related Articles