使用Vector2和Vector2作为通用约束?

时间:2011-03-18 16:22:39

标签: c# generics xna constraints physics

我正在尝试创建一个像这样的通用xna物理模块:

   class PhysicsModule<T> : where T : Vector2, Vector3
   {
        private List<PhysicsForce<T>> _globalForces;

        public PhysicsModule()
        {
            _globalForces = new List<PhysicsForce<T>>();
        }

         /// <summary>
        /// Updates the resultant which will be sent to be applied on all entities.
        /// </summary>
        /// <param name="gameTime">...</param>
        public override void UpdateResultant(GameTime gameTime)
        {
            _resultant = T.Zero;
            foreach (PhysicsForce<T> force in _globalForces)
            {
                T vector = T.Multiply(force.Direction, force.Magnitude);
                T modifiedByTime = T.Multiply(vector, (float)gameTime.ElapsedGameTime.TotalSeconds);

                _resultant = T.Add(_resultant, modifiedByTime);

            }

        }
    }

    class PhysicsForce<T> where T : Vector2, Vector3
    {
        public T Direction;
        public float Magnitude; 
    }

我知道这段代码不起作用,它只是作为一个样本来说明我想做什么。 这是可能的还是我会更好地拥有像这样的抽象基础

class PhysicsModule2D : PhysicsModule 

class PhysicsForce2D : PhysicsForce

1 个答案:

答案 0 :(得分:2)

  1. 您需要始终满足所有通用约束
  2. .net泛型只允许您从通用约束中调用方法,即取消链接它们不按名称工作的C ++模板。这样做的一个结果是您不能在T上使用静态方法或运算符。
  3. 有一种使用动态类型的解决方法(使用C#4中的dynamic关键字或者像MiscUtil那样动态生成代理)。但这会显着降低性能。
  4. 有一个丑陋的黑客允许高性能,但它有点复杂。
  5. 您可以使用一些占位符编写代码,然后使用代码生成器生成其他版本
  6. 您可以手动单独实现2D和3D。即使它违反DRY,也可能是最好的选择。
  7. 对于4),首先创建一个通用接口,其中包含您要使用的VectorX上的所有方法。像这样:

    interface VectorMath
    {
      T Add(T v1,T v2);
    }
    

    然后使用struct实现它。然后将该结构作为第二个通用参数传递给您的类。