Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
641 views
in Technique[技术] by (71.8m points)

inheritance - C# Cannot convert from IEnumerable<Base> to IEnumerable<Derived>

I recently run into trouble when trying to AddRange(IEnumerable) to a List. Probably a classic issue, but I do not really get it yet.

I understand that methods expecting a List parameter are not satisfied with a List, because they might try to add a Base to the List, which is obviously impossible.

But if i get this correctly, since IEnumerables themselves cannot be changed, it ought to work in this case.

The code i thought of looks like this:

class Foo
{
}

class Bar : Foo
{
}

class FooCol
{
    private List<Foo> m_Foos = new List<Foo> ();

    public void AddRange1(IEnumerable<Foo> foos)
    {
        m_Foos.AddRange (foos); // does work
    }

    public void AddRange2<T>(IEnumerable<T> foos) where T : Foo
    {
        m_Foos.AddRange (foos); // does not work
    }
}

class Program
{
    static void Main(string[] args)
    {
        FooCol fooCol = new FooCol ();

        List<Foo> foos = new List<Foo> ();
        List<Bar> bars = new List<Bar> ();

        fooCol.AddRange1 (foos); // does work
        fooCol.AddRange1 (bars); // does not work

        fooCol.AddRange2 (foos); // does work
        fooCol.AddRange2 (bars); // does work
    }
}

I tried to pass a hint to the compiler in the AddRange2 method, but this just moved to problem around.

Is my way of thinking flawed? Is this a limitation of the language or is it by design?

IIRC, support for this kind of operations was added to Java 1.5, so maybe it will be added to C# at some point in the future, too...?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is covariance, and will be fixed in C# 4.0 / .NET 4.0. For now, the generic option is the best answer (for IEnumerable<T> - not IList<T> etc).

But within the generic method, you have to think in terms of T. You could also use Cast<T> or OfType<T> with LINQ to achieve something similar.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...