Тип приведения массива к общему массиву? - PullRequest
3 голосов
/ 28 марта 2010

Краткая версия вопроса - почему я не могу это сделать? Я ограничен .NET 3.5.

T[] genericArray;

// Obviously T should be float!
genericArray = new T[3]{ 1.0f, 2.0f, 0.0f };

// Can't do this either, why the hell not
genericArray = new float[3]{ 1.0f, 2.0f, 0.0f };

Более длинная версия -

Я работаю с движком Unity, хотя это не важно. Что такое - я пытаюсь бросить преобразование между его фиксированным Vector2 (2 числа с плавающей точкой) и Vector3 (3 числа с плавающей точкой) и моим общим классом Vector <> Я не могу привести типы непосредственно к универсальному массиву.

using UnityEngine;

public struct Vector<T>
{
    private readonly T[] _axes;

    #region Constructors
    public Vector(int axisCount)
    {
        this._axes = new T[axisCount];
    }

    public Vector(T x, T y)
    {
        this._axes = new T[2] { x, y };
    }

    public Vector(T x, T y, T z)
    {
        this._axes = new T[3]{x, y, z};
    }

    public Vector(Vector2 vector2)
    {
        // This doesn't work
        this._axes = new T[2] { vector2.x, vector2.y };
    }

    public Vector(Vector3 vector3)
    {
        // Nor does this
        this._axes = new T[3] { vector3.x, vector3.y, vector3.z };
    }
    #endregion

    #region Properties
    public T this[int i]
    {
        get { return _axes[i]; }
        set { _axes[i] = value; }
    }

    public T X
    {
        get { return _axes[0];}
        set { _axes[0] = value; }
    }

    public T Y
    {
        get { return _axes[1]; }
        set { _axes[1] = value; }
    }

    public T Z
    {
        get
        {
            return this._axes.Length < 2 ? default(T) : _axes[2];
        }
        set
        {
            if (this._axes.Length < 2)
                return;

            _axes[2] = value;
        }
    }
    #endregion

    #region Type Converters
    public static explicit operator Vector<T>(Vector2 vector2)
    {
        Vector<T> vector = new Vector<T>(vector2);

        return vector;
    }

    public static explicit operator Vector<T>(Vector3 vector3)
    {
        Vector<T> vector = new Vector<T>(vector3);

        return vector;
    }
    #endregion
}

Ответы [ 4 ]

2 голосов
/ 28 марта 2010

«Универсальный» означает «работает с любой тип».

Ваш пример кода не является общим, потому что он работает только тогда и только тогда, когда T равен float.


Хотя вы не можете преобразовать Vector2D в вектор . Добавьте метод Convert в Vector2D или предоставьте набор методов расширения, например:

public static class VectorExtensions
{
    public static Vector<float> ToGenericVector(this Vector2D vector)
    {
        return new Vector<float>(vector.X, vector.Y);
    }

    public static Vector2D ToVector2D(this Vector<float> vector)
    {
        return new Vector2D(vector.X, vector.Y);
    }
}

Использование:

Vector<float> v = new Vector<float>(3, 5);

Vector2D v2 = v.ToVector2D();
1 голос
/ 28 марта 2010

Вы не можете подразумевать тип универсального параметра из метода.

И, как я уже говорил, ваш опубликованный код не соответствует действительному использованию параметров типа Generic.

Общий параметр должен быть определен в сигнатуре класса или метода.

public class Class1<T>
{
    public T[] Method(params T[] args)
    {
        return args;
    }
}

public class Demo
{
    public Demo()
    {
        var c1 = new Class1<float>();
        float[] result = c1.Method(1.1f, 2.2f);
    }
}
1 голос
/ 28 марта 2010

, если T определен как float, через Vector<T> как Vector<float>, тогда это будет работать (на ограниченном T), но если вы просто хотите локальное преобразование:

var genericArray = new float[3]{ 1.0f, 2.0f, 0.0f };

Конечно, это в любом случае ограничивает T быть float (компилятор не может ничего преобразовать в T и знает это), похоже, вы должны заменить T на float во всем классе, если это так, не так ли? иметь дело с неплавающими векторами?

В этом случае вам нужно что-то вроде:

var genericArray = new T[3]{ X, Y, Z };
0 голосов
/ 28 марта 2010

Вы сказали:

// This doesn't work
this._axes = new T[2] { vector2.x, vector2.y };

Следующее работает (поскольку все может быть преобразовано в object, и последующее преобразование из object в T разрешено, но может произойти сбой во время выполнения, если типы несовместимы, или в этом случае при распаковке не может быть выполнено):

this._axes = new T[2] { (T)(object)vector2.x, (T)(object)vector2.y };

Тем не менее, нет никакого смысла делать класс родовым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...