Geeks With Blogs
Running with Code Like scissors, only more dangerous

C# 2.0 introduced a great new feature to the .NET Type system: generics.  Generics are really cool in that they allow you to define template classes; I can use a single class definition to provide a strongly typed collection, for example.  They enable some other tricks that I would tend to consider something of a "hack" as well; for example, this expression evaluates to true:

   1:  typeof(IEnumerable<int>) != typeof(IEnumerable<double>)

This expression is nice because there are some odd class design decisions in places like the PropertyGrid's type structure.  For example, in order to add a PropertyTab to the list of the PropertyGrid's tabs, you need to add a Type to the PropertyTabCollection exposed by the PropertyGrid's PropertyTabs property.  The PropertyGrid caches the tabs that it creates, and so you can't add a single Type to create two property tabs.  Consequently, even if you override the CreateTab method, you can't expect to add two tabs with the same Type.

My solution, then, was to create ExtensionPropertyTab<T>.  This class's type parameter is utterly useless; I create an arbitrary Type using Reflection Emit, close my ExtensionPropertyTab generic type definition with it, and then add the PropertyTab with that closed type.  Works great!  This stuff will be in an upcoming blog post about my PropertyGridEx project.

All of that is leading up to my next hack and, ultimately, my wishlist item #1 for C# 4.0.

There's a simple design-time class called EnumConverter.  This class is the default type converter for all enumeration types; EnumConverter is what displays the Enum names in the property grid when you're choosing items.  I'm creating a type surrogate class that allows you to customize the names of properties, and I've also been working on displaying better values for enumerations.  To this end, I created the EnumTypeConverter<T> class - this class provides enumeration names, but also retrieves friendly names from attributes on each enum entry.  Using generics, I'm able to cache the friendly names so that reflection only needs to be invoked once; System.Enum does something similar.

What I'd like to do, however, is say this:

   1:  public class EnumTypeConverter<T> : TypeConverter where T : enum

C# doesn't allow me to do this.  I get two errors:

error CS1031: Type expected
error CS1001: Identifier expected

So I try using the type name instead:

   1:  public class EnumTypeConverter<T> : TypeConverter where T : Enum

C# doesn't like this either:

error CS0702: Constraint cannot be special class 'System.Enum'

Why?  I get the same error with System.ValueType, even though ultimately it means the same thing as "struct" (though I could understand this difference).  But I can't do this with System.Delegate either (how about calling Invoke() or BeginInvoke() on T?).

Being able to specify Enum as a base would allow me to:

  • Explicitly cast between T and integral numeric types.
  • Specify 0 as the default value of T rather than using default(T).
  • Perform bitwise operations on them

There's really no reason to have a constraint like "Constraint cannot be special class 'System.Enum'."  Let's eliminate this artificial barrier - there shouldn't be any changes needed to be made to the CLR.

Posted on Tuesday, January 15, 2008 9:34 AM | Back to top

Comments on this post: My C# 4.0 Wishlist, Part 1 : Eliminate Type Constraint Constraints

# re: My C# 4.0 Wishlist, Part 1 : Eliminate Type Constraint Constraints
Requesting Gravatar...
I second that wish!
Left by Tergiver on Feb 16, 2008 7:31 PM

# re: My C# 4.0 Wishlist, Part 1 : Eliminate Type Constraint Constraints
Requesting Gravatar...
I know! I ran into that issue today. I also wish that you could do write an extension to a class that will enable implicit casting. If I had either one of these options then I would never have to cast an enum to a byte and a byte to an enum ever again! :)
Left by Thomas Holloway on Jun 05, 2008 4:24 PM

# re: My C# 4.0 Wishlist, Part 1 : Eliminate Type Constraint Constraints
Requesting Gravatar...
You can get around this but there is a VS bug that mitigates it if you use it with extension methods. The restriction is a C# limit and not an IL limit, so you compile to IL or decompile to IL, change the type and recompile.
Left by BlindWanderer on Aug 25, 2008 7:39 PM

Your comment:
 (will show your gravatar)

Copyright © Robert Paveza | Powered by: