-1

What I want to do:

abstract class TileBase
{
    protected TileGroup<TileBase> tileGroup;
}
class Tile : TileBase
{
    public Tile(Province Province)
    {
        tileGroup = Province;
    }
}
abstract class TileGroup<T>
{
    protected T[] tiles;
    protected TileGroup<TileGroup<T>> tileGroup;
}
class Province : TileGroup<TileBase>
{

    public Province(Tile tile, Nation nation)
    {
        tiles = new[] { tile };
        tileGroup = nation;
    }
}
class Nation : TileGroup<Province>
{

    public Nation(Province province)
    {
        tiles = new[] { province };
        tileGroup = null;
    }
}

This will not work because of invariance (if I understand invariance correctly): cannot convert Nation to TileGroup<TileGroup<TileBase>>

So I'll need to write it like this:

class Nation : TileGroup<TileGroup<TileBase>>
{

    public Nation(Province province)
    {
        tiles = new[] { province };
        tileGroup = null;
    }
}

But when layers get stacked; this gets ugly fast:

Map : TileGroup<TileGroup<TileGroup<TileBase>>> 

This also makes adding layers between two existing layers difficult because one change in a low layer means changing all the higher layers.

So how exactly should I be doing this?


Sorry for the formulation, I know what I want, but not how I should explain it clearer than in this way.

4

1 回答 1

0

为了了解发生了什么以及为什么这不起作用,您需要了解泛型类型实际上是什么。在某种程度上,它们是一种模板,可以根据语言的要求为每个有效的类型提供准确的类型。T

当您编写TileGroup<TileBase>实际发生的是一种新类型时,我们称其TileGroup_TileBase定义如下:

class TileGroup_TileBase
{
    protected TileBase[] tiles;
    protected TileGroup<TileGroup<TileBase>> tileGroup;
}

现在,让我们继续扩展泛型类型。我们已经知道其中的TileGroup<TileBase>类型,但还有一个TileGroup<TileGroup_TileBase>,所以让我们替换它:

class TileGroup_TileBase
{
    protected TileBase[] tiles;
    protected TileGroup_TileGroup_TileBase tileGroup;
}
class TileGroup_TileGroup_TileBase
{
    protected TileGroup_TileBase[] tiles;
    protected TileGroup<TileGroup<TileGroup_TileBase>> tileGroup;
}

我们可以在这里继续,但这实际上足以解释问题。让我们看一下您要在构造函数Nation中分配的内容。是 a ,所以让我们扩展一下:ProvinceNationTileGroup<Province>

class TileGroup_Province
{
    protected Province[] tiles;
    protected TileGroup<TileGroup<Province>> tileGroup;
}

好的,所以我们的类型已经足够扩展了。让我们看一下您正在尝试执行的任务。在Province中,该tileGroup属性是 type TileGroup<TileGroup<TileBase>>,所以本质上这就是您要执行的操作:

TileGroup<Province> nation = null;
TileGroup<TileGroup<TileBase>> province_tileGroup = nation;

你能明白为什么现在失败了吗?如果没有,让我们在这里使用我们扩展的泛型类型:

TileGroup_Province nation = null;
TileGroup_TileGroup_TileBase province_tileGroup = nation;

好的,这就是实际使用的类型(请记住,我们这样做并不是为了理解这一点,而是这些泛型类型实际上会为每个类型T真正实现!)。但是如果我们看上面的定义,实际上TileGroup_ProvinceTileGroup_TileGroup_TileBase没有关系。当然,它们看起来很相似,但没有类型关系允许这种分配!

这就是为什么当我们在 BCL 中处理泛型类型时,我们经常有接口。因为接口允许我们在这些泛型类型实现之间建立类型关系,然后我们可以使用它们将一个分配给另一个。老实说,具有这些受保护字段的抽象类使得使用接口清理它有点困难,因此您可能应该考虑是否真的需要这种类型关系以及是否为这些字段提供抽象基类型实际上是必要的。

于 2017-08-20T13:06:29.033 回答