对派生类使用非泛型基类集合?

时间:2012-07-31 20:10:54

标签: c# c#-4.0 collections

嗯,很难用语言来解释。所以这是一个例子。在SDL .NET API中,有一个名为SpriteCollection的类,它被设计为......精灵的集合。但问题是由于某种原因,开发人员决定不使SpriteCollection泛型,如.NET List<>类。所以,我想,它只适用于Sprite类或从Sprite继承的其他类?无论如何,假设我从Tile派生Sprite。我添加了两个新属性:

class Tile : Sprite
{

    public Tile(char symbol = default(char), bool solid = true)
    {
        Symbol = symbol;
        Solid = solid;
    }

    public char Symbol
    {
        get;
        set;
    }

    public bool Solid
    {
        get;
        set;
    }
}

现在,如何将SpriteCollectionTile一起使用,仍然可以使用TileSolid专有属性?

一个(可能是愚蠢的)解决方案可能是这样的:

Tile t = (Tile) myCollection[i];
if (t.Solid) { ... }

有没有更好的办法做这样的事情?

3 个答案:

答案 0 :(得分:3)

您将SpriteCollection的返回值转换为Tile的建议是实现这一目标的方法。如果您需要使用提供的集合类并且无法更改它,则没有更好的选项。

答案 1 :(得分:1)

如果您希望在迭代时避免强制转换,则可以覆盖GetEnumerator方法。

public class TileList: SpriteList {

    public new IEnumerator<Tile> GetEnumerator()
    {
        foreach (var tile in GetBase())
        {
            if (tile is Tile)
            {
                yield return tile as Tile;
            }
        }
    }

    protected SpriteList GetBase()
    {
        return (SpriteList )this;
    }
}

(这当然是强制转换,但它将该转换封装在枚举器中。)

答案 2 :(得分:0)

  

现在,我如何在Tiles中使用SpriteCollection并仍然能够使用像Solid这样的Tile独有属性?

你可以通过某种形式的演员来做到这一点。您的方法有效,但我个人会使用:

Tile t = myCollection[i] as Tile;
if (t != null)
{
    if (t.Solid) { ... }
}

这允许您安全地将Tile实例以及其他精灵添加到集合中。

如果您使用通用类,例如List<Sprite>,则会出现同样的问题。这将允许您使用任何Sprite子类,而不仅仅是Tile。为了拥有一个没有强制转换的类型安全集合,你必须使用List<Tile>,这会限制你的集合中只有瓷砖,而不是其他精灵。