Share via


Death by a thousand cuts

As you might have noticed from my posts in the past I really dislike it when there is a part of the C# language that seems to be unnecessarily lacking.  For example, not being able to take a delegate to a property.  It's a perfectly reasonable thing to do.  You run into it in practice.  And, it's something that is completely possible to do without any difficulty in the language.  Having methods be able to do this but not have properties (which are just glorified methods) have the same capability just annoys me.  Similaryly, not having something as nice as covariant return types is also quite aggravating.  It could be added without breaking any code, and it ends up making life much nicer for both API developers and consumers.

There are an enormous number of these "nuisances", and (unsurprisingly) we've found one more.  It's often the case that you want to have an operation that works specifically on an enum.  For example you might want to take the unsafe Enum.Parse method and replace it with a typesafe one.  Currently Enum.Parse looks like.

class Enum

{

public static Enum Parse(Type enumType, string enumMemberName) { ... }

}

 

To use it you have to write code like:

Color c = (Color)Color.Parse(typeof(Color), someString);

 

(holy redundancy batman!) *shudder*.

So i'd love to be able to write something helpful like this:

class EnumUtilities<T> where T : enum

{

     public static T Parse(string enumMemberName)

     {

          return (T)Enum.Parse(typeof(T), enumMemberName);

     }

     //Returns true if there is a single member in this enum equal to "value"

     public bool IsMember(T value) { ... }

     //Returns true if "value" can be represented as the union of any members of this enum

     public bool IsUnionOfMembers(T value) { ... }

}

...

Color c = EnumUtilities<Color>.Parse(someString);

Debug.Assert(EnumUtilities<Color>.IsMember(someColorHandedToYouByAnother));

 

Seems reasonable right?  A useful way to get around the limitations of the built in enum type by using generics.  And, instead of the ugly non-typesafe redundant calls you need to do now you have a nice safe method that is checked at compile type to be ok.

But... no.

Of course, once again, i try to do this and i experience another cut.  "enum is not a valid constraint for a type parameter".  Sigh...

We already allow you to contrain to reference types or value types.  So why not allow you to constrain to enums?  It's just one of those missing things that really annoys you once you hit it.  Of course, there are workarounds.  You could do this:

class EnumUtilities<T> where T : struct

{

     static EnumUtilities

     {

          if (!typeof(T).IsSubclassOf(typeof(Enum)))

          {

              throw new ArgumentException("The type parameters T must be an enum");

          }

}

     public static T Parse(string enumMemberName)

     {

          return (T)Enum.Parse(typeof(T), enumMemberName);

     }

}

...

//Compiles fine and fails at runtime

int c = EnumUtilities<int>.Parse(someString);

 

I hate having things fail at runtime.  I'm a big fan of the compiler figuring this all out for me and telling me right when i compile.  But, nope.  Once again I have no choice but ugly workarounds and asking myself "why couldn't this just be consistant?"

Comments

  • Anonymous
    March 22, 2005
    The comment has been removed
  • Anonymous
    March 22, 2005
    I went ahead and submitted a suggestion:
    http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackId=FDBK23140
  • Anonymous
    March 22, 2005
    I've commented out on this matter before:

    This is regarding Enum restriction on generics :

    http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=FDBK16420

    As well - there were suggestion about exactly the same issue at
    http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=FDBK14577

    Even more - using generics for enums was suggested by me at betaplace at 6/19/2004 as 320417672

    ;-))

    P.S> Cyrus, you have so many bugs in your code that it does not even compile ;-)
    Instead of (!typeof(T).IsSubclassOf(typeof(Enum)) you can use
    (!typeof(T).IsEnum).
    As well - throwing exceptions in static constructor is not good.

    Personaly I preffer TryParse() aproach (BTW, also missing)
  • Anonymous
    March 22, 2005
    The comment has been removed
  • Anonymous
    March 22, 2005
    An enum constraint would be a good thing. I'm afraid that if it doesnt go in now, though adding possible constraints in the future may be too late.

    See also: http://philiprieck.com/blog/archive/2005/02/17/537.aspx
  • Anonymous
    March 22, 2005
    On defining delegates to properties... you actually can do it with some reflection magic... I talked about it a while ago on my blog:

    http://schweitn.blogspot.com/2004/03/wrapping-up-properties-with-delegates.html
  • Anonymous
    March 23, 2005
    Agreed, great post Cyrus.
  • Anonymous
    March 23, 2005
    Eric: That would absolutely be possible. But what about what happens when you get to a method that we didn't think about? We can't just jam a kajillion methods into Enum and hope that they suffice. So you want an extensible solution that will work in all cases for whatever the developer has in mind.
  • Anonymous
    March 23, 2005
    Philip: Could you expand on this a little more. Why would it be too late if it didn't go in now? If it was added in the future it could be used without breaking backwards compatability.
  • Anonymous
    March 23, 2005
    The comment has been removed
  • Anonymous
    March 23, 2005
    Cyrus: Agreed... yet the workaround does exist... and it's good for people to know about it I think. You work with what you're given.
  • Anonymous
    March 23, 2005
    The comment has been removed
  • Anonymous
    March 23, 2005
    Joe: Will that allow me to do:

    Parse<System.Enum>("someVal");

    or will it restrict it to only enums that aren't System.Enum (which isn't an enum).

    That's one of the slight difference between the "sruct" constraint and the System.ValueType consrtaint. (it also related to how Nullable is treated)
  • Anonymous
    March 23, 2005
    The comment has been removed
  • Anonymous
    March 23, 2005
    "I would find it particularly appealing if C# supported the keyword in the context of something like "is". The use of ":" to indicate "is" is particularly annoying to me."

    You and me both. However I suspect that it is now far far to late in C# history to ever change such a thing.

    I also feel the same way about the : for class extension and interface implementation, but maybe it's just my java heritage showing.
  • Anonymous
    March 24, 2005
    The comment has been removed
  • Anonymous
    August 24, 2005
    Your site is realy very interesting. http://www.bignews.com
  • Anonymous
    February 21, 2006
    theworldhotels fr