简体   繁体   中英

Use Non-Generic Base Class Collection for Derived Class?

Well, it's hard to explain it in words. So here's an example. In the SDL .NET API, there's a class called SpriteCollection which is designed to be, well... a collection of sprites. However the problem is that for some reason the developers decided to not make SpriteCollection generic, like the .NET List<> class. So, I guess, it can only work with the Sprite class or other classes that inherit from Sprite ? Anyway, let's say I derive Tile from Sprite . And I add two new properties to it:

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;
    }
}

Now, how can I use the SpriteCollection with Tile s and still be able to use the Tile exclusive properties like Solid ?

One (probably stupid) solution would perhaps be this:

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

Is there any better way to do something like this?

Your proposal to cast the return values of the SpriteCollection to Tile is the way to do it. You do not have better options if you need to use the collection class provided and cannot change it.

If you wanted to avoid casting as you iterate you way through, you could override the GetEnumerator method.

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;
    }
}

(This does of course cast, but it encapsulates that casting in the enumerator.)

Now, how can I use the SpriteCollection with Tiles and still be able to use the Tile exclusive properties like Solid?

You can do this via a cast of some form. Your method works, though I personally would use:

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

This allows you to add your Tile instances, but also other sprites to the collection safely.

The same issue arises if you use a generic class, such as List<Sprite> . This will allow you to use any Sprite subclass, not just Tile . In order to have a type safe collection without casting, you'd have to use List<Tile> , which would restrict you to only tiles, not other sprites, within your collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM