简体   繁体   中英

Generic types operators

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?

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

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;
    }

    ...

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));

        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM