0

I would like to make a method that "transforms" one space to another. This is quite a simple thing to template in C++ but in C# I'm not sure which interface/type or how I need to use the "where" clause in order to get the compiler to understand what I want. My C++ function looked like this:

template<class T>
T Transform(T s, T s1, T s2, T d1, T d2)
{
        T result = (s - s1) / (s2 - s1) * (d2 - d1) + d1;       

        return result;
}   

and my first stab at a generic C# version (in extension methods), looks like this:

public static T Transform<T>(T s, T s1, T s2, T d1, T d2)
{
        T result = (s - s1) / (s2 - s1) * (d2 - d1) + d1;       

        return result;
}

Alas C# would like me to be more specific about the types, i.e.

"error CS0019: Operator '-' cannot be applied to operands of type 'T' and 'T'".

What does C# want me to do?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Robinson
  • 9,666
  • 16
  • 71
  • 115
  • You cant do arithmetic operations on generic types. See [this](http://stackoverflow.com/questions/32664/is-there-a-constraint-that-restricts-my-generic-method-to-numeric-types) post for more. – Yuval Itzchakov Aug 18 '14 at 10:10
  • That's odd. I would have thought you just need to tell it that "T" overloads or has operator +, -, /, *. – Robinson Aug 18 '14 at 10:12

1 Answers1

3

You cannot directly tell the compiler via a constraint that T implements a certain operator. You can only tell the compiler that T implements some class. If this class overloads the operator, then you can use it.

For example, a class that defines the '-' operator

public class Stuff
{
    public Stuff(int number) {
        Number = number;
    }

    public int Number { get; set; }

    public static Stuff operator -(Stuff a, Stuff b) {
        return new Stuff(a.Number - b.Number);
    }

    //Define the other operators in the same way...
}

Then, in your method, you can do this:

public static T Transform<T>(T s, T s1, T s2, T d1, T d2)
    where T : Stuff
{
    Stuff result = (s - s1) / (s2 - s1) * (d2 - d1) + d1;
    return (T)result;
}

Alternatively, you can just use dynamic, but that will throw an exception if the operator does not exist.

Dennis_E
  • 8,751
  • 23
  • 29
  • Thanks. Seems like a bit of an oversight (or some technical reason) why types like int, double and so on don't implement some kind of INumeric. Anyway I'm not comfortable with this solution even though it's neat. I think perhaps specialised functions for float and double will be enough. – Robinson Aug 18 '14 at 13:33
  • Yes, you're right. Many people complain about the fact they have to write the same overloaded method for each primitive type. It's a very minor problem imo. I think this solution is a bit ugly, too. It's just the way it is. C# is still a cool enough language. – Dennis_E Aug 18 '14 at 13:41