如何使T继承类?

时间:2015-03-23 16:47:28

标签: c#

我正在为一个roguelike编程一个地牢生成器。我有一个名为Room的基类。它包含可由其他类型的房间继承的方法。它看起来像这样,但后来更先进

class Room
{
   protected virtual void Construct() { /*make square room here*/ }
}
class RoundRoom : Room
{
   protected override void Construct() { /*make round room here*/ }
}

我的课堂产生房间需要“喂养”房间来生成。房间处理建筑,我有不同类型的房间。我希望它可以根据某些条件或机会生成某些特定的房间。

所以我用不同类型的房间喂它。首先我想到了这个:

    class RoomEntry
    {
        public Point chance;
        public Room room;
    }

然后有一个数组

RoomEntry[] entries;

然后只是喂它

Generator.Feed(entries[random.Next(0, 10)].room); // just an example

但那不行!如果我在生成器中编辑房间,它也将在RoomEntry中更改!而且我需要使用它好几次! 所以,如果我根据某些房间类型制作房间......它会工作!

所以我想出了这个:

class RoomPlanner
{
    class RoomEntry<T> where T : Room, new()
    {
        public Point chance;
        T r;

        public Room RoomToBuild()
        {
            return new T();
        }
    }

    RoomEntry<Room>[] entrys;

    public void Foo()
    {
        entrys = new RoomEntry<Room>[10];

        for (int i = 0; i < entrys.Length; i++)
        {
            entrys[i] = new RoomEntry<RoundRoom>();
        }
    }
}

但那是不可能的。我收到了这个错误:

Cannot implicitly convert type 'Super_ForeverAloneInThaDungeon.RoomPlanner.RoomEntry<Super_ForeverAloneInThaDungeon.RoundRoom>' to 'Super_ForeverAloneInThaDungeon.RoomPlanner.RoomEntry<Super_ForeverAloneInThaDungeon.Room>'

那么,我怎样才能让它接受从Room继承的类,或者我如何采用不同的方法解决这个问题呢?

这不是this的副本。这是一个不同的问题,我没有足够的信息来完全解决我的问题。

2 个答案:

答案 0 :(得分:3)

问题是协变/逆变类型参数只能与接口或委托类型一起使用。 (this MSDN article中有关此内容的详细信息。)基本上,即使约束为RoomEntry<T>,也无法声明与RoomEntry<Room>具有逆差的T : room

您可以通过定义由IRoomEntry实现的RoomEntry<T>接口来解决这个问题,如下所示:

interface IRoomEntry
{
    Room RoomToBuild();
}

class RoomPlanner
{
    class RoomEntry<T> : IRoomEntry
        where T : Room, new()
    {
        public Point chance;
        T r;

        public Room RoomToBuild()
        {
            return new T();
        }
    }

    IRoomEntry[] entrys;

    public void Foo()
    {
        entrys = new IRoomEntry[10];

        for (int i = 0; i < entrys.Length; i++)
        {
            entrys[i] = new RoomEntry<RoundRoom>();
        }
    }
}

答案 1 :(得分:1)

好像你只想Clone房间,然后再把它送到Generator。您只需在Clone课程中添加Room方法:

Room Clone() { return (Room)this.MemberwiseClone(); }

然后像这样喂它:

Generator.Feed(entries[random.Next(0, 10)].room.Clone());