1

I'm trying to create 2D vectors which coordinates are generic(Vector2Dint, Vector2Dfloat, etc...) to be able to do some math operations easier. I've seen this question is pretty close to mine: Can't operator == be applied to generic types in C#? but my case is with "*" operator. Basically I need to make some math functions like "cross" or "dot" for this vectors, one example is this one:

    public static T cross<T>(Vec2<T> u, Vec2<T> v)
    {
        return u.x * v.y - u.y * v.x;
    }

The thing is Visual Studio tells me the same: "Operator '*' cannot be applied to operands of type 'T' and 'T' " (T is the type of the coordinate). My thought was to overload the ' *' operator inside the class "Vec2" to be able to multiply these coordinates, having this:

    public static Vec2<T> operator *(T x, T y)
    {
        return x * y;
    }

But Visual Studio again tells me the same thing again. I'm sure I'm not overloading operators in the right way but I don't know the reason. Thanks for the help

EDIT 1: Ok so what we can learn from this is, if you want to define a function for diferent types (int, float, double, etc...) and you want performance, the best way to do it is defining the function for each type, but now, another problem comes up for me. If you have a very long function or several long functions, ¿is this still being the best way?

Community
  • 1
  • 1
dolm
  • 37
  • 3
  • You don't know what type x and y are, what makes you think they have the `*` operator? – Powerlord Feb 26 '16 at 21:33
  • http://stackoverflow.com/a/9486094/3922214 – Jonathan Carroll Feb 26 '16 at 21:35
  • Ok, T is wrong for sure, if you defined a Vec2 then your operator will be for two integers, and you want to multiply the vectors, not two integers, am I right? – Gusman Feb 26 '16 at 21:35
  • Well, not exactly that, I am trying to create a function to do the "cross" mathematical function that multiplies each coord of the vector, this coordinates are generic, which are int, float and double. The problem appears when i try to multiply the coordinates – dolm Feb 26 '16 at 21:42

3 Answers3

0

It is currently impossible to tell the compiler which operators can be used on generic type parameters. The issue of expanding generic constraints in a number of ways is being discussed on github in the C# compiler repository under the paragraph titled Interesting but require CLR support.

You can also vote for this feature to be added on Visual Studio Uservoice

TKharaishvili
  • 1,997
  • 1
  • 19
  • 30
0

You get this error because the type "T" is unknown. For all you know, it could be a string, or any kind of class or struct.

One way to do it is to provide overloads for all "expected" types of the vector

    public static int cross(Vec2<int> u, Vec2<int> v)
    {
        return u.x * v.y - u.y * v.x;
    }

    public static double cross(Vec2<double> u, Vec2<double> v)
    {
        return u.x * v.y - u.y * v.x;
    }

    public static long cross(Vec2<long> u, Vec2<long> v)
    {
        return u.x * v.y - u.y * v.x;
    }

    public static float cross(Vec2<float> u, Vec2<float> v)
    {
        return u.x * v.y - u.y * v.x;
    }

    ...
Shazi
  • 1,490
  • 1
  • 10
  • 22
  • I think this is the best way to do it, if the expected types are only 4 I can deal with that. – dolm Feb 26 '16 at 21:53
  • @daolmed It's yours to decide whether 4 types are sufficient or not. There are more than a dozen numeric types in .net – TKharaishvili Feb 26 '16 at 21:58
0

Well, here is a really ugly way to do it, I would never use it for a game (speed) but it acomplishes what you asked:

Your Vec2 class:

    public class Vec2<T>
    {
        public T x;
        public T y;

        public static Vec2<T> operator *(Vec2<T> u, Vec2<T> v)
        {
            return u.Cross(v);
        }
    }

And an extension class:

    public static class Exts
    {
        public static T Cross<T>(this Vec2<T> u, Vec2<T> v)
        {

            if (u.x is double)
                return (T)Convert.ChangeType(Convert.ToDouble(u.x) * Convert.ToDouble(v.y) - Convert.ToDouble(u.y) * Convert.ToDouble(v.x), typeof(T));
            else if (u.y is float)
                return (T)Convert.ChangeType(Convert.ToSingle(u.x) * Convert.ToSingle(v.y) - Convert.ToSingle(u.y) * Convert.ToSingle(v.x), typeof(T));
            else if (u.x is decimal)
                return (T)Convert.ChangeType(Convert.ToDecimal(u.x) * Convert.ToDecimal(v.y) - Convert.ToDecimal(u.y) * Convert.ToDecimal(v.x), typeof(T));
            else
                return (T)Convert.ChangeType(Convert.ToInt32(u.x) * Convert.ToInt32(v.y) - Convert.ToInt32(u.y) * Convert.ToInt32(v.x), typeof(T));

        }
    }
Gusman
  • 14,905
  • 2
  • 34
  • 50
  • Thank you so much for the answer, but you were right, is for a game! – dolm Feb 26 '16 at 21:52
  • Then, my two cents, NEVER use generics for games, and less in a case like the Vector class as you will have thousands of them and they're slower than direct classes. – Gusman Feb 26 '16 at 21:54