游戏编程,原型模式:如何将泛型类从 C++ 转换为 C#?

问题描述

在这本名为 Game Programming Patterns 的引人入胜的书中,在 Prototype 示例中,作者展示了如何使用泛型类在游戏中生成怪物。

免责声明:作者确实声明该代码仅用于举例说明一个概念(可能并不完美)

这是给定示例中的 C++ 代码

class Spawner
{
public:
  virtual ~Spawner() {}
  virtual Monster* spawnMonster() = 0;
};

template <class T>
class SpawnerFor : public Spawner
{
public:
  virtual Monster* spawnMonster() { return new T(); }
};

调用类将运行:

Spawner* ghostSpawner = new SpawnerFor<Ghost>();

我已经尝试将这个例子翻译成 C#,所以它可以在 Unity 中的一个场景中进行测试:

public class Spawner<T> {
    public virtual Monster SpawnMonster() {
        return null;
    }
}

class SpawnerTemplate<T> : Spawner { 
    public override Monster SpawnMonster() {
        return new T();
    }
}

场景中的脚本将运行:

  var ghost = new Spawner<Ghost>();

Visual Studio 无法编译,因此我重写为以下内容

class SpawnerTemplate<T> : Spawner where T : new(){ 
    public override Monster SpawnMonster() {
        return new T() as Monster;
    }
}

调用时仍然存在编译错误

var ghost = new SpawnerTemplate<Ghost>();

必须是具有公共无参数构造函数的非抽象类型才能将其用作参数

这是 Ghost 代码的样子:

public class Ghost : Monster
{
    public Ghost (int health,int speed) {
        this.health = health;
        this.speed = speed;
    }

    public override Monster Clone() {
        return new Ghost(health,speed);
    }
}

我从 C++ 到 C# 的翻译是否正确?

谢谢

解决方法

不确定这个模式在 C# 中的用处,但是:

public class Monster
{
}

public class Ghost : Monster
{
}

public abstract class Spawner
{
    public abstract Monster SpawnMonster();
}

public class SpawnerFor<T> : Spawner where T : Monster,new()
{
    public override Monster SpawnMonster() { return new T(); }
}

然后:

var spawnerForGhost = new SpawnerFor<Ghost>();
var ghost = spawnerForGhost.SpawnMonster();

C# 中的最大限制是您可以为无参数构造函数 (,new()) 的存在定义约束,如本例所示,但例如,如果您希望 new Monster() 接收为某些东西作为参数 (new Monster(location)),然后它会崩溃(您不能对参数构造函数进行约束。您可以在 public abstract Initialize(Location location) 中明确定义一个 Monster 并从 {{ 1}}).