Я пытаюсь создать 2D-векторы с общими координатами (Vector2Dint, Vector2Dfloat и т. Д.), Чтобы облегчить выполнение некоторых математических операций. Я видел, что этот вопрос довольно близок к моему: Может » t operator == применяться к универсальным типам в C #?, но в моем случае используется оператор "*". В основном мне нужно сделать некоторые математические функции, такие как «крест» или «точка» для этих векторов, один из примеров - это:

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

Дело в том, что Visual Studio говорит мне то же самое: «Оператор '*' не может применяться к операндам типа 'T' и 'T'» (T - это тип координаты). Я решил перегрузить оператор '*' внутри класса Vec2, чтобы иметь возможность умножать эти координаты, имея это:

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

Но Visual Studio снова говорит мне то же самое. Я уверен, что неправильно перегружаю операторы, но не знаю причины. Спасибо за помощь

РЕДАКТИРОВАТЬ 1: Итак, что мы можем извлечь из этого, если вы хотите определить функцию для разных типов (int, float, double и т. д.), и вам нужна производительность, лучший способ для этого нужно определить функцию для каждого типа, но теперь у меня возникает другая проблема. Если у вас очень длинная функция или несколько длинных функций, это все еще лучший способ?

1
dolm 27 Фев 2016 в 00:30

3 ответа

Лучший ответ

Вы получаете эту ошибку, потому что тип «T» неизвестен. Насколько вам известно, это может быть строка, любой класс или структура.

Один из способов сделать это - предоставить перегрузки для всех «ожидаемых» типов вектора.

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

    ...
0
Shazi 26 Фев 2016 в 21:45

Что ж, вот действительно уродливый способ сделать это, я бы никогда не использовал его для игры (скорость), но он выполняет то, что вы просили:

Ваш класс Vec2:

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

И класс расширения:

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

        }
    }
0
Gusman 26 Фев 2016 в 21:47

В настоящее время невозможно указать компилятору, какие операторы могут использоваться для параметров универсального типа. Проблема расширения общих ограничений несколькими способами обсуждается на github в репозитории компилятора C # под абзацем под заголовком Интересно, но требуется поддержка CLR .

Вы также можете проголосовать за добавление этой функции на Visual Studio Uservoice

0
TKharaishvili 26 Фев 2016 в 21:52