Casting Type array to Generic array?
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
}
"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>, 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();
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 };
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);
}
}
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.
精彩评论