67

Now that we have enum constraint, why doesn't compiler allow me to write this code?

public static TResult? ToEnum<TResult>(this String value, TResult? defaultValue)
    where TResult : Enum
{
    return String.IsNullOrEmpty(value) ? defaultValue : (TResult?)Enum.Parse(typeof(TResult), value);
}

The compiler says:

Error CS0453 The type 'TResult' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'

13
  • 5
    @DanielleSummers At least until C#8 where we get nullable reference types... Commented May 15, 2018 at 13:41
  • 2
    @DavidG - meanwhile I'm still waiting for non-nullable reference types... Commented May 15, 2018 at 13:42
  • 2
    @JamesFaix It's not really supposed to be a new generic constraint. It's the same constraint that has always been valid in CIL but has been artificially restricted in C# until 7.3. Because of that, I don't expect it to be useful to report it as a bug. Commented May 15, 2018 at 13:43
  • 1
    @KirillKovalenko: System.Enum is a special class(which can't be used as type parameter constraint anyway). It is so special that it inherits from System.ValueType but is a reference type. stackoverflow.com/questions/14561338/… Commented May 15, 2018 at 13:45
  • 4
    @mjwills Because the Enum base class is a weird case in the .NET type hierarchy, and all classes that inherit from it are value types. I thought the new constraint was akin to the class or struct constraints, not just allowing a base class constraint that was forbidden before. Commented May 15, 2018 at 13:46

2 Answers 2

113

You can, but you have to add another constraint: the struct constraint.

public static void DoSomething<T>(T? defaultValue) where T : struct, Enum
{
}
Sign up to request clarification or add additional context in comments.

6 Comments

That isn't a workaround. It is just what the specs tell us to do @KirillKovalenko
@PatrickHofman Can you link to the specs? I must have missed that part in my reading.
Because Nullable<T> requires T to be a struct type @thermite.
Thanks @patrick, I found it in the docs for nullable. I was looking in the docs at enums and generics...
The docs for Nullable<T> show the where T : struct constraint. learn.microsoft.com/en-us/dotnet/api/… . Here is the constraint in the source code: github.com/microsoft/referencesource/blob/master/mscorlib/… / github.com/dotnet/runtime/blob/v5.0.0-preview.5.20278.1/src/…
|
20

Because System.Enum is a class, you cannot declare a variable of type Nullable<Enum> (since Nullable<T> is only possible if T is a struct).

Thus:

Enum? bob = null;

won't compile, and neither will your code.

This is definitely strange (since Enum itself is a class, but a specific Enum that you define in your code is a struct) if you haven't run into it before, but it is clearly a class (not a struct) as per the docs and the source code.

1 Comment

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.