Используя Vector2 и Vector2 как общие ограничения? - PullRequest
2 голосов
/ 18 марта 2011

Я пытаюсь создать несколько общий физический модуль 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 Ответ

2 голосов
/ 18 марта 2011
  1. Вы должны всегда выполнять все общие ограничения
  2. .net-шаблоны позволяют вам вызывать методы только из общего ограничения, то есть отсоединять шаблоны C ++, которые они не работают по имени. Одним из следствий этого является то, что вы не можете использовать статические методы или операторы на T.
  3. Существует обходной путь, использующий динамическую типизацию (используя ключевое слово dynamic в C # 4 или генерируя делегаты на лету, как это делает MiscUtil). Это значительно снижает производительность.
  4. Есть некрасивый хак, который позволяет высокую производительность, хотя это немного сложно.
  5. Вы можете написать код с некоторыми заполнителями, а затем использовать генератор кода для генерации других версий
  6. Вы можете просто реализовать 2D и 3D отдельно вручную. Вероятно, лучший выбор, даже если он нарушает СУХОЙ.

Для 4) вы сначала создаете общий интерфейс, который содержит все методы в VectorX, которые вы хотите использовать. Как это:

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

Затем вы реализуете это, используя struct s. А затем вы передаете эту структуру в качестве второго универсального параметра вашему классу.

...