Casting integers to generic parameters

I

Israel

I want to create a bunch of generic interfaces based on a enum but
they need to convert from an integer value to that enum. The goal is
to make type safe interfaces to non-type safe 3rd party interfaces
which only provide integers and documentation. I can use Convert to
go in the other direction but it doesn't seem to be clicking in my
head how to convert from an integer to some enum type - or force the
compiler to realize that the generic type MUST be an enum.

This is kind of what I’m thinking but you can’t declare that a type
derives from System.Enum:

class Class1<TType> where TType : System.Enum
{
public Class1(int value)
{
m_Value = (TType)value;
}

TType Value
{
get
{
return m_Value;
}
}
TType m_Value;
}
 
P

Pavel Minaev

I want to create a bunch of generic interfaces based on a enum but
they need to convert from an integer value to that enum.  The goal is
to make type safe interfaces to non-type safe 3rd party interfaces
which only provide integers and documentation.  I can use Convert to
go in the other direction but it doesn't seem to be clicking in my
head how to convert from an integer to some enum type - or force the
compiler to realize that the generic type MUST be an enum.

This is kind of what I’m thinking but you can’t declare that a type
derives from System.Enum:

Yes, that's a rather strange C# restriction (CLR doesn't have it, and
e.g. C++/CLI does let you constrain your generic type parameters to
System.Enum as you want). There's no other way to do it, but you can
do a conversion nonetheless. One little-known fact about enum types is
that you can actually unbox a raw int or uint value directly into an
enum type. So, in your case, you can just do this:

m_Value = (TType)(object)value

Note that you do not need any constraint on TType now, as the downcast
from object to TType is valid for any TType. Of course, this will
still fail for any TType that cannot actually be unboxed from an int
(which is int itself, uint, and any enum type).
 
I

Israel

  m_Value = (TType)(object)value

Having better type safety would be nice but this conversion will due
since my interface will be providing a type safe interface to unsafe
interfaces clients won't be abusing this class unless they try to
create their own and then do something silly like pass a string as the
type.

It seems to me that the 'where' clause of generic definitions is very
limited. Forcing the support of interfaces is nice but forcing other
constraints is hard like creating a generic interpolator which
requires that you can perform standard mathematical operations on the
class e.g. +,-,/,* If I created a class for complex numbers which
supported all of that I wouldn't be able to easily use it or int or
double. There should be some standard ISupportMath interface. While
I'm on a rant it also annoys me that enums support IComparable but
don't support IComparable<int>.
 
P

Pavel Minaev

It seems to me that the 'where' clause of generic definitions is very
limited.  Forcing the support of interfaces is nice but forcing other
constraints is hard like creating a generic interpolator which
requires that you can perform standard mathematical operations on the
class e.g. +,-,/,*  If I created a class for complex numbers which
supported all of that I wouldn't be able to easily use it or int or
double.  There should be some standard ISupportMath interface.  While
I'm on a rant it also annoys me that enums support IComparable but
don't support IComparable<int>.

It's rather well-known that C# generics are fairly limited. Then
again, the only production quality language today that I know that
does everything that you want (and then some) is Haskell with its type
classes. Well, maybe also Scala, though I'm not sure how polished that
one is. We will probably get there some day, but definitely not
tomorrow. If you check the issue tracker at MS Connect, you'll see
that all those suggestions are already there, often with many
duplicates. So we can be sure that the C# team is aware of the issue,
and it is somewhere on their customer request list. Of course, so's a
lot of other stuff...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top