我最近在尝试将AddRange(IEnumerable)添加到列表时遇到麻烦。可能是经典问题,但我还没有真正理解。

我知道期望List参数的方法对List并不满意,因为它们可能会尝试将Base添加到List中,这显然是不可能的。

但是,如果我正确地做到这一点,由于IEnumerables本身无法更改,因此在这种情况下应该可以使用。

我想到的代码如下所示:

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

我试图在AddRange2方法中向编译器传递一个提示,但这只是解决了问题。

我的思维方式有缺陷吗?这是语言的限制还是设计上的限制?

IIRC,对此类操作的支持已添加到Java 1.5中,所以也许将来还会在C#中添加它……?

最佳答案

这是协方差,将在C#4.0/.NET 4.0中修复。目前,泛型选项是最佳答案(对于IEnumerable<T>-not IList<T> etc)。

但是在通用方法中,您必须考虑T。您也可以在LINQ中使用Cast<T>OfType<T>来实现类似的目的。

07-24 09:50
查看更多