通用类型运算符
Generic types operators
我正在尝试创建坐标通用的 2D 向量(Vector2Dint、Vector2Dfloat 等),以便能够更轻松地进行一些数学运算。我已经看到这个问题非常接近我的问题:Can't operator == be applied to generic types in C#? 但我的情况是“*”运算符。基本上我需要为这个向量做一些数学函数,比如 "cross" 或 "dot",一个例子是这个:
public static T cross<T>(Vec2<T> u, Vec2<T> v)
{
return u.x * v.y - u.y * v.x;
}
事情是 Visual Studio 告诉我相同的:"Operator '*' cannot be applied to operands of type 'T' and 'T' "(T 是坐标的类型)。我的想法是重载 class "Vec2" 中的 ' *' 运算符,以便能够乘以这些坐标,具有:
public static Vec2<T> operator *(T x, T y)
{
return x * y;
}
但是 Visual Studio 再次告诉我同样的事情。我确定我没有以正确的方式重载运算符,但我不知道原因。感谢帮助
编辑 1: 好的,我们可以从中学到的是,如果您想为不同类型(int、float、double 等)定义一个函数并且您想要性能,最好的方法是为每种类型定义函数,但是现在,我又遇到了另一个问题。如果您有一个很长的函数或几个长函数,这仍然是最好的方法吗?
目前无法告诉编译器哪些运算符可以用于泛型类型参数。 github in the C# compiler repository 上标题为 有趣但需要 CLR 支持.
的段落下正在讨论以多种方式扩展通用约束的问题
您也可以在 Visual Studio Uservoice
上投票支持要添加的此功能
您收到此错误是因为类型 "T" 未知。如您所知,它可以是字符串,或任何类型的 class 或结构。
一种方法是为所有 "expected" 类型的向量提供重载
public static int cross(Vec2<int> u, Vec2<int> v)
{
return u.x * v.y - u.y * v.x;
}
public static double cross(Vec2<double> u, Vec2<double> v)
{
return u.x * v.y - u.y * v.x;
}
public static long cross(Vec2<long> u, Vec2<long> v)
{
return u.x * v.y - u.y * v.x;
}
public static float cross(Vec2<float> u, Vec2<float> v)
{
return u.x * v.y - u.y * v.x;
}
...
好吧,这是一个非常丑陋的方法,我永远不会将它用于游戏(速度),但它完成了你的要求:
你的 Vec2 class:
public class Vec2<T>
{
public T x;
public T y;
public static Vec2<T> operator *(Vec2<T> u, Vec2<T> v)
{
return u.Cross(v);
}
}
还有一个扩展 class:
public static class Exts
{
public static T Cross<T>(this Vec2<T> u, Vec2<T> v)
{
if (u.x is double)
return (T)Convert.ChangeType(Convert.ToDouble(u.x) * Convert.ToDouble(v.y) - Convert.ToDouble(u.y) * Convert.ToDouble(v.x), typeof(T));
else if (u.y is float)
return (T)Convert.ChangeType(Convert.ToSingle(u.x) * Convert.ToSingle(v.y) - Convert.ToSingle(u.y) * Convert.ToSingle(v.x), typeof(T));
else if (u.x is decimal)
return (T)Convert.ChangeType(Convert.ToDecimal(u.x) * Convert.ToDecimal(v.y) - Convert.ToDecimal(u.y) * Convert.ToDecimal(v.x), typeof(T));
else
return (T)Convert.ChangeType(Convert.ToInt32(u.x) * Convert.ToInt32(v.y) - Convert.ToInt32(u.y) * Convert.ToInt32(v.x), typeof(T));
}
}
我正在尝试创建坐标通用的 2D 向量(Vector2Dint、Vector2Dfloat 等),以便能够更轻松地进行一些数学运算。我已经看到这个问题非常接近我的问题:Can't operator == be applied to generic types in C#? 但我的情况是“*”运算符。基本上我需要为这个向量做一些数学函数,比如 "cross" 或 "dot",一个例子是这个:
public static T cross<T>(Vec2<T> u, Vec2<T> v)
{
return u.x * v.y - u.y * v.x;
}
事情是 Visual Studio 告诉我相同的:"Operator '*' cannot be applied to operands of type 'T' and 'T' "(T 是坐标的类型)。我的想法是重载 class "Vec2" 中的 ' *' 运算符,以便能够乘以这些坐标,具有:
public static Vec2<T> operator *(T x, T y)
{
return x * y;
}
但是 Visual Studio 再次告诉我同样的事情。我确定我没有以正确的方式重载运算符,但我不知道原因。感谢帮助
编辑 1: 好的,我们可以从中学到的是,如果您想为不同类型(int、float、double 等)定义一个函数并且您想要性能,最好的方法是为每种类型定义函数,但是现在,我又遇到了另一个问题。如果您有一个很长的函数或几个长函数,这仍然是最好的方法吗?
目前无法告诉编译器哪些运算符可以用于泛型类型参数。 github in the C# compiler repository 上标题为 有趣但需要 CLR 支持.
的段落下正在讨论以多种方式扩展通用约束的问题您也可以在 Visual Studio Uservoice
上投票支持要添加的此功能您收到此错误是因为类型 "T" 未知。如您所知,它可以是字符串,或任何类型的 class 或结构。
一种方法是为所有 "expected" 类型的向量提供重载
public static int cross(Vec2<int> u, Vec2<int> v)
{
return u.x * v.y - u.y * v.x;
}
public static double cross(Vec2<double> u, Vec2<double> v)
{
return u.x * v.y - u.y * v.x;
}
public static long cross(Vec2<long> u, Vec2<long> v)
{
return u.x * v.y - u.y * v.x;
}
public static float cross(Vec2<float> u, Vec2<float> v)
{
return u.x * v.y - u.y * v.x;
}
...
好吧,这是一个非常丑陋的方法,我永远不会将它用于游戏(速度),但它完成了你的要求:
你的 Vec2 class:
public class Vec2<T>
{
public T x;
public T y;
public static Vec2<T> operator *(Vec2<T> u, Vec2<T> v)
{
return u.Cross(v);
}
}
还有一个扩展 class:
public static class Exts
{
public static T Cross<T>(this Vec2<T> u, Vec2<T> v)
{
if (u.x is double)
return (T)Convert.ChangeType(Convert.ToDouble(u.x) * Convert.ToDouble(v.y) - Convert.ToDouble(u.y) * Convert.ToDouble(v.x), typeof(T));
else if (u.y is float)
return (T)Convert.ChangeType(Convert.ToSingle(u.x) * Convert.ToSingle(v.y) - Convert.ToSingle(u.y) * Convert.ToSingle(v.x), typeof(T));
else if (u.x is decimal)
return (T)Convert.ChangeType(Convert.ToDecimal(u.x) * Convert.ToDecimal(v.y) - Convert.ToDecimal(u.y) * Convert.ToDecimal(v.x), typeof(T));
else
return (T)Convert.ChangeType(Convert.ToInt32(u.x) * Convert.ToInt32(v.y) - Convert.ToInt32(u.y) * Convert.ToInt32(v.x), typeof(T));
}
}