C# 无法从 IEnumerable<Base> 转换为 IEnumerable<Derived>

标签 c# inheritance collections ienumerable

我最近在尝试将 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 .您也可以使用 Cast<T>OfType<T>使用 LINQ 来实现类似的功能。

关于C# 无法从 IEnumerable<Base> 转换为 IEnumerable<Derived>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/634268/

相关文章:

.net - 为什么 resharper 建议 : "Return type can be IEnumerable<T>"?

python 乘以两个收集计数器

c# - 如何对集合的保存进行单元测试

javascript - typescript - 如何获取对象类实例?

C# 将非模态形式放在模态形式前面?

c# - 不使用内置成员资格功能时使用 FormsAuthentication.SignOut 是否有意义

c# - 我需要使用 Linq 比较列表和数据表并过滤值

c++ - 我怎么知道指向基类对象的指针数组中元素的类型是什么,它将为派生类分配内存

java - 从2个类继承不同的 boolean 值

c# - 是否可以通过 Dynamics Nav 2016 中的 ODATA 查询所有公司