繁体   English   中英

为什么我不能通过 IList<childtype> 到 F(IEnumerable<parenttype> )?</parenttype></childtype>

[英]Why can't I pass IList<ChildType> to F(IEnumerable<ParentType>)?

我想我可以将IList<ChildClass>作为IEnumerable<ParentClass>传递,因为显然 ChildType 列表中的每个 object 也是 ParentType 的实例。 但我对编译器没有兴趣。 我错过了什么?

编辑:添加了我想要的 function Foo3 。 谢谢!

namespace StackOverflow
{
    public class ParentClass
    {
    }

    public class ChildClass : ParentClass
    {
    }

    public class Test
    {
        // works
        static void Foo(ParentClass bar2)
        {
        }

        // fails
        static void Foo2(IEnumerable<ParentClass> bar)
        {
        }

        // EDIT: here's the right answer, obtained from the 
        // Charlie Calvert blog post 
        static void Foo3<T>(IEnumerable<T> bar) where T : ParentClass
        {
        }

        public static void Main()
        {
            var childClassList = new List<ChildClass>();

            // this works as expected
            foreach (var obj in childClassList)
                Foo(obj);

            // this won't compile
            // Argument '1': cannot convert from 
            // 'System.Collections.Generic.List<ChildClass>' 
            // to 'System.Collections.Generic.IEnumerable<ParentClass>' 
            Foo2(childClassList);

            // EDIT: this works and is what I wanted
            Foo3(childClassList);
        }
    }
}

因为 generics 不是 co/contra 变体:

Eric Lippert 的博客对此有一篇很棒的文章。

Charlie Calvert 的另一篇文章在这里

您应该在Eric Lippert 的 Covariance and Contravariance 系列中找到您要查找的所有内容。 这是一个相当多的阅读,但回答了(a)为什么你不能在 C# 3.0 中做到这一点,以及(b)为什么你能够在 C# 4.0 中做到这一点。

恐怕没有对泛型参数类型的隐式转换(没有“泛型方差”似乎是技术术语)。 不确定我能否给你更深入的解释,但我会接受它作为 CLR 的工作方式......

您只需使用 childClassList 上的Cast扩展方法将列表转换为 IEnumerable。

虽然在 IList 和 IEnumerable 的情况下一切正常,但当您将其视为集合和集合时,编译器无法真正知道这一点。

如果您可以将集合用作集合,则有人可以尝试将 Parent 添加到集合中……编译器必须防止这种情况发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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