2010-03-28 3 views
3

Короткий вариант вопроса - почему я не могу это сделать? Я ограничен .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 }; 

Longer версия -

Я работаю с двигателем 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 
} 
+3

Ваш класс не является полным. Я не вижу никакого общего параметра. Неполный код хуже, чем никакого кода. ;-) –

+0

@Sky Код был завершен, но Джордж не смог правильно скрыть HTML ('' ...). –

+0

@ Konrad & George. Да, я должен был это понять. Сожалею. –

ответ

2

средств "Generic" "работает с любого типа".

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


В то время как вы не можете преобразовать Vector2D в вектор < T & GT, вы можете, конечно, конвертировать 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(); 
+0

Короткий вариант, да. Но вся идея в том, что Vector может быть чем угодно - я использовал его для int, float, double. Unity имеет тип Vector2 и Vector3, который я хочу, чтобы иметь возможность конвертировать в и из, поэтому я могу иметь дело с моей более полной универсальной версией, но кормить любые Unity-функции своими фиксированными типами. т.е.: v = new Vector (3); Vector3 v3 = v; –

+0

Отлично - спасибо! –

1

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

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

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

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

var genericArray = new T[3]{ X, Y, Z }; 
1

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

И, как я уже говорил ранее, ваш опубликованный код не представляет собой действительное использование параметров типа 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); 
    } 
} 
+0

Смотрите мой комментарий выше. –

0

Вы сказали:

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

Сказанное не имеет смысла делать класс общим.

Смежные вопросы