【问题标题】:Why can't I pass IList<ChildType> to F(IEnumerable<ParentType>)?为什么我不能将 IList<ChildType> 传递给 F(IEnumerable<ParentType>)?
【发布时间】:2009-03-10 21:41:52
【问题描述】:

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

编辑:添加了我想要的功能 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);
        }
    }
}

【问题讨论】:

    标签: c#


    【解决方案1】:

    因为泛型不是 co/contra 变体:

    Eric Lippert's blog 在这方面有一篇很棒的帖子。

    来自Charlie Calvert is here的另一篇文章。

    【讨论】:

      【解决方案2】:

      【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          如果您可以将集合用作集合,那么有人可以尝试将 Parent 添加到集合中......编译器必须阻止这种情况。

          【讨论】:

            猜你喜欢
            • 2012-01-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-03-04
            • 1970-01-01
            • 1970-01-01
            • 2013-06-25
            • 1970-01-01
            相关资源
            最近更新 更多