Col*_*old 8 generics dynamic type-constraints c#-4.0
在尝试Vector2<int/float/double>在C#中实现泛型之后,我自己遇到了这个问题,我已经对这个问题进行了一系列调查,这个问题也有描述:
这些链接包含更多背景信息和迷人的解决方案方法:
http://www.yoda.arachsys.com/csharp/genericoperators.html
http://www.codeproject.com/KB/cs/genericnumerics.aspx
既然C#4.0已经推出了新的多功能dynamic类型,我对这个精彩的SO社区的问题是:它是一个可以用来构建高性能,通用Vector/Matrix /等的工具.数字类型?
显然,Vector2可以通过以下方式构建:
public struct Vector2
{
public dynamic X;
public dynamic Y;
public Vector2(dynamic x, dynamic y)
{
this.X = x;
this.Y = y;
}
public static Vector2 operator+(Vector2 a, Vector2 b)
{
return new Vector2(a.X + b.X, a.Y + b.Y);
}
}
Run Code Online (Sandbox Code Playgroud)
但是使用这种方法我们在这里没有类型约束,所以你可以做一个Vector2(3, 12.4572).有没有一种方法可以将动态成员与类型参数混合Vector2<int>来执行我们的数学运算,就像使用ints一样?
也许某种形式的铸造可以用来确保this.X是T,虽然我不知道它会如何表现.
只有您可以判断动态操作员调用是否符合您的性能要求,但是通过泛型来解决您的某些类型安全问题当然是可能的 - 没有理由因为一个小的动态调用而无需在运行时检查所有内容:
// Consider making this type immutable
public struct Vector2<T>
{
public T X;
public T Y;
public Vector2(T x, T y)
{
this.X = x;
this.Y = y;
}
// The only dangerous operation on the type
public static Vector2<T> operator +(Vector2<T> a, Vector2<T> b)
{
return new Vector2<T>((dynamic)a.X + b.X, (dynamic)a.Y + b.Y);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,唯一危险的操作是实际添加 2个相同类型的向量(加法运算符需要在类型参数上按预期工作),但其他一切都是完全类型安全的,应该是.你不能这样做new Vector<int>("a", 5),添加一个Vector<int>和一个Vector<string>,或者Vector<int>为a 添加两个s Vector<string>.请注意,在原始解决方案的编译时,不会捕获这些错误.
注意:
没有什么可以阻止你在这里使用泛型,而是沿着compiling-an-expression-tree路由添加而不是dynamic.委托调用不是免费的,但理论上它们应该比dynamic这种情况下的方法更快- 至少,你避免使用拳击值类型.但是,只有你可以判断它们是否足够快.
在所有情况下,考虑编写一个静态构造函数来验证type-argument实际上是否具有合适的加法运算符,以便在游戏的早期发生类型错误.
编辑(OP不满意dynamic这里的表现):
表达式树方法看起来像:
public struct Vector2<T>
{
private static readonly Func<T, T, T> Add;
// Create and cache adder delegate in the static constructor.
// Will throw a TypeInitializationException
// if you can't add Ts or if T + T != T
static Vector2()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Add = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
public T X;
public T Y;
public Vector2(T x, T y)
{
this.X = x;
this.Y = y;
}
public static Vector2<T> operator +(Vector2<T> a, Vector2<T> b)
{
// Delegate invocation instead of dynamic operator invocation.
return new Vector2<T>(Add(a.X, b.X), Add(a.Y, b.Y));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1393 次 |
| 最近记录: |