【问题标题】:GameProgramming, Prototype pattern: How to translate generic class from C++ to C#?GameProgramming,原型模式:如何将泛型类从 C++ 转换为 C#?
【发布时间】:2020-12-28 16:05:55
【问题描述】:

在这本引人入胜的名为 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# 的翻译是否正确?

谢谢

【问题讨论】:

  • 你能提供你的 Ghost 类的样子吗?我怀疑您没有定义公共 Ghost() 构造函数。
  • 您确定Ghost 继承自Monster(其中Monster 在C# 中可能是一个接口)?同样在 C# 中,我相信有一种方法可以指定您的泛型必须遵守某个接口。所以你可能会说class SpawnerTemplate&lt;T&gt; where T : Moster
  • 我在问题中添加了 Ghost 类。 Monster 是一个基类(但目前不是抽象的)。这种代码架构背后的逻辑称为模板。我不确定将 SpawnerTamplate T 更改为 Monster,它应该是什么,因为 SpawnerTemplate 是 Spawner 类的模板。我想。

标签: c# c++ class generics prototype-programming


【解决方案1】:

不确定这种模式在 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)),然后它就崩溃了(你不能对有参数的构造函数有约束。你可以在Monster 中明确定义一个public abstract Initialize(Location location) 并从SpawnMonster(Location location) 调用它)。

【讨论】:

    猜你喜欢
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    相关资源
    最近更新 更多