28

To constrain a generic type parameter to be of an enum type, I previously constrained them like this, which was the best I could go for constraining type T for enums in pre-C# 7.3:

void DoSomething<T>() where T : struct, IComparable, IConvertible, IFormattable

Now, C# 7.3 adds a new feature to constrain a generic type to System.Enum. I tried using the enum constraint with the VS2017 15.7 update released today, and it compiles successfully when I write it like this (given I have a using System; directive):

void DoSomething<T>() where T : Enum

However, using the enum keyword does not work and causes the compiler to throw the following errors (there are more errors following, expecting a method body, but not really worth mentioning here I guess):

void DoSomething<T>() where T : enum
                                ^ error CS1031: Type expected
                                  error CS1002: ; expected
                                    ^ error CS1001: Identifier expected
                                      error CS1514: { expected
                                      error CS1513: } expected

Since there is a struct constraint working for structures, I do not understand why enum doesn't work here for enums. It's true that enum does not map to an actual type like int would do for Int32, but I thought it should behave the same as the struct constraint.

Did I just fall into an experimental feature trap not being fully implemented yet, or was this done on purpose in the specification (why?)?

6
  • While string is an alias for the String type, the same is not true for the enum keyword and the Enum type. Commented May 7, 2018 at 16:42
  • That's what I meant with my last paragraph. A struct constraint is not an alias for a specific type too, but is possible. Commented May 7, 2018 at 16:43
  • struct is for the value types, not just struct, similar to class for all reference types Commented May 7, 2018 at 16:51
  • check this, possible solution stackoverflow.com/a/79903/1559611 Commented May 7, 2018 at 16:56
  • @MrinalKamboj It does make sense, kinda. Though I think one could argue then that those keywords handle their own specific cases, and enum should've done too. About your link: with C# 7.3 using Enum (not the keyword enum) would be the better solution now. The question is just why the keyword isn't meant to work (at the moment). Commented May 7, 2018 at 16:58

1 Answer 1

18

The struct constraint on generics doesn't map to an actual type (though it could, in theory, map to ValueType). Similarly, enum doesn't cleanly map to actual types the way string, int, or long do, it sets up special syntax for creating a class of symbolic constants that map to integer values; hence public enum Stuff instead of public class Stuff : Enum. Note that had the latter been implemented instead, it would be more subtle since it would change syntax based on inherited type, instead of changing syntax based on a non-class keyword.

So, in conclusion, yes, where T : enum is not meant to work because enum is a keyword, not a type alias. If you really want to see it work because enum at least smells like a type alias in context like these, go request it!

EDIT: For some historical reference, here's a question from 2008 indicating that Enum was not a valid constraint, since it's a special class.

Sign up to request clarification or add additional context in comments.

2 Comments

I guess this is the best explanation so far. I couldn't find others on GitHub where the implementation of this feature was discussed. Funny enough, people there originally provided samples which also used the enum keyword, but it wasn't implemented like that in the end.
@RayKoopa Also, I am a bit surprised that if you have just where T : Enum, then the compiler will allow you to use the abstract base type System.Enum itself (a reference type!) for T. So you could DoSomething<Enum>();. To avoid that, it is actually legal to do where T : struct, Enum. To me it looks like that is what you want 99.9% of the time! Ah, I see now there is a linked thread about just this.

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.