tags:

views:

1887

answers:

3

What is the reason behind C# not allowing type constraints on Enum's? I'm sure there is a method behind the madness, but I'd like to understand why it's not possible.

Below is what I would like to be able to do (in theory).

public static T GetEnum<T>(this string description) where T : Enum
{
...
}
+16  A: 

This is an occasionally requested feature.

As I'm fond of pointing out, ALL features are unimplemented until someone designs, specs, implements, tests, documents and ships the feature. So far, no one has done that for this one. There's no particularly unusual reason why not; we have lots of other things to do, limited budgets, and this one has never made it past the "wouldn't this be nice?" discussion in the language design team.

The CLR doesn't support it, so in order to make it work we'd need to do runtime work in addition to the language work.

I can see that there are a few decent usage cases, but none of them are so compelling that we'd do this work rather than one of the hundreds of other features that are much more frequently requested, or have more compelling and farther-reaching usage cases. (If we're going to muck with this code, I'd personally prioritize delegate constraints way, way above enum constraints.)

Eric Lippert
Thanks Eric, I was hoping you would answer that one :). I would really like this feature too, even though it's not a "must-have"...
Thomas Levesque
I don't see how that's true. On the contrary, the ground state would be to allow it, and the restriction didn't exist until someone made the CS0702 compiler errror.
SLaks
The CLR does support it, at least according to my understanding of page 166 f the spec.
SLaks
Funny you mentioned delegate constraints because I'd love to see those as well.
Taylor Leese
Last time I overheard a conversation about this with the CLR guys they said that they didn't have the gear in place for it, but it is entirely possible that I was misunderstanding what they were talking about.
Eric Lippert
Let's put it this way -- is there a way to do it with ILASM?
Eric Lippert
SLaks
Somehow I missed this post before. In another question, this blog post has been linked: http://weblogs.asp.net/kennykerr/archive/2005/05/16/The-Case-of-the-Missing-Generic-_2800_Parse-Method_2900_.aspx That suggests that it *is* available in IL. I seem to remember trying it before and it working, although that might have been for `Delegate`. I'd be happy to experiment with this a bit more (heck, a *lot* more) if it might mean the restrictions being removed from C# 5. (I assume C# 4 is locked down now.)
Jon Skeet
I'm confused as to why you state the CLR does not support Enum constraints, as it does both according to page 166/167 of the CLI ECMA document (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf) (that is, unless the CLR does not conform to the CLI spec) and the work of Jon Skeet in Unconstrained Melody (http://code.google.com/p/unconstrained-melody/).
RCIX
Well then, ask yourself what's more likely? That the spec is wrong and Jon's implementation is fictitious, or that I'm misremembering or misinterpreting a conversation I had with the CLR guys about this over a year ago?
Eric Lippert
If you are well known enough to be on Channel 9 then all of your answers must be 100% correct 100% of the time ;-)
Jason Jackson
+19  A: 

Actually, it is possible, with an ugly trick. However, it cannot be used for extension methods.

public abstract class Enums<Temp> where Temp : class {
    public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
        return (TEnum)Enum.Parse(typeof(TEnum), name); 
    }
}
public abstract class Enums : Enums<Enum> { }

Enums.Parse<DateTimeKind>("Local")

If you want to, you can give Enums<Temp> a private constructor and a public nested abstract inherited class with Temp as Enum, to prevent inherited versions for non-enums.

Note that you can't use this trick to make extension methods.

SLaks
This does work for delegates, except that it won't exclude `Delegate` itself.
SLaks
Clever! And yet, oh so horrible.
Gregory
A: 

One quirky thing here is that there are a fair number of generic Enum methods you might want to write whose implementation depends on the "base" type of the enumeration.

By the "base" type of an enumeration, E, I mean the type in the System namespace whose name is the same as the name of the member of System.TypeCode enumeration obtained by calling System.Type.GetTypeCode(System.Type) for the type E. If the enumeration was declared in C#, this is the same type that it was declared to "inherit" from (I'm not sure what this is officially called in the spec). For example, the base type of the Animal enumeration below is System.Byte:

public enum Animal : byte
{
    Moose,
    Squirrel
}

It's possible to write such methods using switch statements, but it sure is ugly, you can't get strongly typed parameters or return types whose type is the base type of the enumeration, and you have to either repeat the metadata lookup or do some caching (e.g. in the static constructor for the generic type containing the method).

Doug McClean