6

I have a generic type that should be specified with an Enum type (actually, it's one of several specified enums, but I'll settle for System.Enum).

Of course the compiler balks at code like:

class Generic<T> where T : Enum {}

with a "Constraint cannot be special class 'System.Enum'" exception.

The only solution I've been able to come up so far is using the static type initializer to inspect the type parameter and throw an exception if it is not, in fact, an Enum, like this:

class Generic<T> 
{
  static Generic()
  {
    if (typeof(T).BaseType != typeof(Enum))
      throw new Exception("Invalid Generic Argument");
  }
}

which at least gives me runtime security that it wont we used with a non-enum parameter. However this feels a bit hacky, so is there a better way to accomplish this, ideally with a compile-time construct?

SWeko
  • 30,434
  • 10
  • 71
  • 106
  • possible duplicate of [Anyone know a good workaround for the lack of an enum generic constraint?](http://stackoverflow.com/questions/7244/anyone-know-a-good-workaround-for-the-lack-of-an-enum-generic-constraint) – nawfal Jan 29 '14 at 10:19

4 Answers4

6

You can use Jon Skeet's Unconstrained Melody project to do this.

Using Unconstrained Melody you would write:

class Generic<T> where T : IEnumConstraint

Which would accomplish the same thing.

More info about Unconstrained Melody with usage examples.

Anders Gustafsson
  • 15,837
  • 8
  • 56
  • 114
MattDavey
  • 8,897
  • 3
  • 31
  • 54
  • At first look, this is promising. Tnx for the link. I think I've actually read that one, and that was part of the feeling I had that "I was doin' it wrong" – SWeko Jan 04 '13 at 16:20
4

Unfortunately, there is no way to ensure that a type passed to a generic class is an enum at compile time. You can only add the following constraint:

class Generic<T> where T : struct { }

In order to exclude all reference types, but the runtime check will still be necessary.

e_ne
  • 8,340
  • 32
  • 43
1

I think you can use Struct:

class Generic<T> where T : Struct
levelnis
  • 7,665
  • 6
  • 37
  • 61
1

enums also implement the IConvertible interface, so you can add that as a constraint, along with the struct.

class Generic<T> where T : struct, IConvertible {}
Fermin
  • 34,961
  • 21
  • 83
  • 129