开发者

C#: Semantics for generics?

I have a list:

private readonly IList<IList<GameObjectController>> removeTargets;
private readonly IList<IList<GameObjectController>> addTargets;

PickUp inherits from GameObjectController. But when I try this:

public IList<PickUp> Inventory

// ... 

gameObjectManager.MoveFromListToWorld(this, user.Model.Inventory);

// ...

    // This queues everythin开发者_如何学运维g up to be removed, until ProcessMoves...() is called
    public void MoveFromWorldToList(GameObjectController removedFromWorld, IList<GameObjectController> addTarget)
    {
        toBeRemoved.Add(removedFromWorld);
        addTargets.Add(addTarget);
    }

// ...

    /// <summary>
    /// Removes all the GameObjects on which removal is requested from the world.
    /// </summary>
    public void ProcessMovesFromListToWorld()
    {
        for (int i = 0; i < toBeAdded.Count; i++)
        {
            GameObjectController moved = toBeAdded[i];
            addGameObjectToWorld(moved);

            if (removeTargets[i] != null)
            {
                removeTargets[i].Remove(moved);
            }
        }
        toBeAdded.Clear();
        removeTargets.Clear();
    }

I get a compiler error:

cannot convert from 'System.Collections.Generic.IList<PickUp>' to 'System.Collections.Generic.IList<GameObjectController>'

Why does this occur? Shouldn't this be fine, since PickUp is a subclass of GameObjectController? Do I need something like Java's Map<E extends GameObjectController>?

Earlier, I was having a similar problem, where I was trying to implicitly cast inventory from an IList to an ICollection. Is this the same problem?


See my other answer here:
How to return an IQueryable<Something> as an IQueryable<ISomething>

Short version:

Remember that IList<PickUp> and IList<GameObjectController> are two (and only two) completely different classes in the type system. The only inheritance relationship they have comes from the System.Collections branch of the inheritance tree; there is none at all on the GameObjectController branch of the inheritance tree. You might as well try to cast an IList<double> to an IList<ArgumentNullException>.

What you can do instead is call the Cast<T>() extension method that is available for IEnumerable<T>.


You can't convert List<BaseClass> to List<DerivedClass>. Here is a recent question that deals with this issue.


This is called co- and contravariance and is first supported in c# 4.0. And even then it only works with IEnumerable and not IList.


A list of base objects can certainly hold items of derived objects. What I cannot gather from your code, however, is exactly what you're doing. You have an IList<IList<class>>, and then the implementation of your method is not visible to us. But code like the following certainly works (Bar extends Foo)

IList<Foo> foos = new List<Foo>();
IList<Bar> bars = new List<Bar>() { new Bar(), new Bar() };
foreach (Bar bar in bars)
    foos.Add(bar);

Maybe you're trying to the below scenario? This is where you have a list of lists of base ofjects and a list of lists of derived objects? If so, you can cast like below.

IList<IList<Foo>> listOfFoos = new List<IList<Foo>>() { foos };
IList<IList<Bar>> listOfBars = new List<IList<Bar>>() { bars };

foreach (IList<Bar> b in listOfBars)
{
    listOfFoos.Add(b.Cast<Foo>().ToList());
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜