views:

301

answers:

4

The short version of the question - why can't I do this? I'm restricted to .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 version -

I'm working with the Unity engine here, although that's not important. What is - I'm trying to throw conversion between its fixed Vector2 (2 floats) and Vector3 (3 floats) and my generic Vector<> class. I can't cast types directly to a generic array.

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
}
+1  A: 

if T is defined as float, via Vector<T> as Vector<float> then this will work (on a restricted T), but if you just want a local conversion:

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

Of course, this restricts T to being a float anyway (the compiler can't convert just anything to T and knows this), it looks like you should replace T with float in the whole class if that's the case, are you dealing with non-float vectors?

In that case you need something like:

var genericArray = new T[3]{ X, Y, Z };
Nick Craver
+2  A: 

"Generic" means "works with any type".

Your example code is not generic, because it only works if and only if T is float.


While you can't convert a Vector2D to a Vector<T&gt, you can, of course, convert a Vector2D to a Vector<float>. Add a Convert method to Vector2D or provide a set of extension methods like this:

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

Usage:

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

Vector2D v2 = v.ToVector2D();
dtb
The short version, yes. But the whole idea is that Vector<T> can be anything - i've used it for int, float, double. Unity has a Vector2 and Vector3 type which I want to be able to convert to and from so I can deal with my far superior generic version, but feed any Unity functions their fixed types. ie:Vector<float> v = new Vector<float>(3);Vector3 v3 = v;
George R
Excellent - thankyou!
George R
A: 

You cannot imply the type of a generic parameter from within a method.

And, as I stated before, your posted code does not represent a valid usage of Generic type parameters.

The generic parameter is to be defined in the class or method signature.

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);
    }
}
Sky Sanders
See my comment above.
Konrad Rudolph
A: 

You said:

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

The following works (since everything can be converted to object, and the subsequent conversion from object to T is permitted but may fail at runtime if the types aren’t compatible, or in this case if unboxing cannot be performed):

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

That said, it makes absolutely no sense to make the class generic.

Konrad Rudolph