我有以下多个结构:Vector2,Vector3,Vector4。每个结构都有为基本算术运算以及隐式和显式强制转换定义的运算符重载。
到目前为止,我已经在Vector4类中添加了所有可能的组合:
public static Vector4 operator + (Vector4 v1, Vector4 v2) { return (new Vector4(...)); }
public static Vector4 operator + (Vector4 v1, Vector3 v2) { return (new Vector4(...)); }
public static Vector4 operator + (Vector3 v1, Vector4 v2) { return (new Vector4(...)); }
public static implicit operator Vector4 (Vector2 v) { return (new Vector4(v)); }
public static implicit operator Vector4 (Vector3 v) { return (new Vector4(v)); }
public static explicit operator Vector3 (Vector4 v) { return (new Vector3(v)); }
public static explicit operator Vector2 (Vector4 v) { return (new Vector2(v)); }
是否有关于哪些运算符更适合哪种结构的指南?我无法想象会以哪种方式损害性能,但我想知道如果其他开发人员遇到此代码,对他们来说更直观的事情将引起我的兴趣。操作员组合的数量迅速增加到几十种。
顺便说一句,在其他类中复制这些运算符不会引起编译时错误。我没有检查过将调用哪个实现,但是除此之外。
如果每个类代表二维,三维和四维向量,我认为您应该可以减少代码量。这是因为只要您具有必要的隐式上转换,不同维向量之间的向量算术定义都是多余的。因此,将不需要像下面这样的运算符:
public static Vector4 operator + (Vector4 v1, Vector3 v2) { return (new Vector4(...)); }
public static Vector4 operator + (Vector3 v1, Vector4 v2) { return (new Vector4(...)); }
我还建议使低维向量处理高维向量的上转换和下转换。这是因为下变频会剥离信息,而如何进行选择应采用“更有限”的结构。
因此,VectorI
结构将需要对所有结构进行隐式上转换,VectorI+J
并对所有VectorI-J
结构进行显式下转换。另外,VectorI结构将需要实现自己的矢量算法。但是,由于“ I”仅具有值2、3和4,这意味着:
Vector2需要对Vector3和Vector4的隐式转换,以及对Vector3和Vector4的显式下变频。
Vector3需要隐式转换为Vector4,还需要从Vector4进行显式下变频。
Vector4不需要转换。
所有4个结构仅在相同维数的向量之间就自己实现了线性代数方法。
我刚刚测试了该方案,并添加了完全不同的Vector2,Vector3和Vector4结构,并完成了隐式转换。
更新资料
刚刚做了一个快速的原型实现加法,所有跨维度的加法均按预期工作:
public struct Vector2
{
public double x, y;
public Vector2(double x, double y)
{
this.x = x; this.y = y;
}
#region linear algebra
public static Vector2 operator +(Vector2 first, Vector2 second)
{
return new Vector2(first.x + second.x, first.y + second.y);
}
#endregion
#region conversions to/from higher dimensions
public static implicit operator Vector3(Vector2 v2)
{
return new Vector3(v2.x, v2.y, 0);
}
public static implicit operator Vector4(Vector2 v2)
{
return new Vector4(v2.x, v2.y, 0, 0);
}
public static explicit operator Vector2(Vector3 v3)
{
return new Vector2(v3.x, v3.y);
}
public static explicit operator Vector2(Vector4 v4)
{
return new Vector2(v4.x, v4.y);
}
#endregion
}
public struct Vector3
{
public double x, y, z;
public Vector3(double x, double y, double z)
{
this.x = x; this.y = y; this.z = z;
}
#region linear algebra
public static Vector3 operator +(Vector3 first, Vector3 second)
{
return new Vector3(first.x + second.x, first.y + second.y, first.z + second.z);
}
#endregion
#region conversions to/from higher dimensions
public static implicit operator Vector4(Vector3 v3)
{
return new Vector4(v3.x, v3.y, v3.z, 0);
}
public static explicit operator Vector3(Vector4 v4)
{
return new Vector3(v4.x, v4.y, v4.z);
}
#endregion
}
public struct Vector4
{
public double x, y, z, w;
public Vector4(double x, double y, double z, double w)
{
this.x = x; this.y = y; this.z = z; this.w = w;
}
#region linear algebra
public static Vector4 operator +(Vector4 first, Vector4 second)
{
return new Vector4(first.x + second.x, first.y + second.y, first.z + second.z, first.w + second.w);
}
#endregion
}
以下测试代码可以正常运行:
public static class VectorHelper
{
public static void Test()
{
var v2 = new Vector2(5, 5);
var v3 = new Vector3(7, 7, 7);
var v4 = new Vector4(3, 3, 3, 3);
var res1 = v2 + v3;
Debug.Assert(res1.GetType().Name == "Vector3"); // No assert
var res2 = v3 + v4;
Debug.Assert(res2.GetType().Name == "Vector4"); // No assert
var res3 = v2 + v4;
Debug.Assert(res3.GetType().Name == "Vector4"); // No assert
Debug.Assert(res3.x == 8 && res3.y == 8 && res3.z == 3 && res3.w == 3); // No assert
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句