7

I have some code that looks like this:

class A<T>
      where T : // what should I say here to make this work?
{
   void foo()
   {
      int x = 0;
      T y = (T)x; // this is a compile error without proper type restrictions
   }
}

The intent is to use A with types like double, float, int.

user1124310
  • 111
  • 4

4 Answers4

3

You can't have a type constraint for this, unfortunately. However, you can use the Convert.ChangeType method.

class A<T>
{
   void foo()
   {
      int x = 0;
      T y = (T)Convert.ChangeType(x, typeof(T));
   }
}

This won't stop you from instantiating the class with a type that can't be converted from an int, though.

Random832
  • 37,415
  • 3
  • 44
  • 63
3

int, float, double keywords are just syntactic sugar. The compiler maps them to value types like Int32, Float, Double etc (which are structs). Generally you can't force a type T to be a only a primitive type but you can impose T to be a value type by doing:

class A<T>
  where T : struct
{
   void foo()
   {
      int x = 0;
      T y = (T)Convert.ChangeType(x, typeof(T));  
   }
}

Please note that you still need to use Convert.ChangeType as pointed out by Random832. Imposing the type T to be a struct is only to exclude classes (which are not value types). It's not a great advantage but I think it's cleaner.

There is a similar question here anyway.

hope it helps.

Community
  • 1
  • 1
codingadventures
  • 2,924
  • 2
  • 19
  • 36
1

No you can't. If you are gonna use this method with only value types you can specify a struct constraint, otherwise you can't restrict T to be, float,int,double only.

There is way to get rid of compiler error, you can box the value then cast it back, but it's not a good idea and practice, because this will fail if the type of x and T are not compatible:

T y = (T)(object)x
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
1

I can suggest one way to do it(but it's far from being elegant, to be honest):

interface IConvertsFromNumeric<T>
{
    T FromLong(long x);
    T FromDouble(double x);
    T FromDecimal(decimal x);
}

class A<T>
  where T : IConvertsFromNumeric<T>, new()
{
   void foo()
   {
      int x = 0;
      T y = new T().FromLong(x);
   }
}
alex.b
  • 4,547
  • 1
  • 31
  • 52
  • This cannot be made to handle the predefined types, though. You're stuck with the interfaces they implement already, you can't add your own. –  Mar 08 '15 at 00:24