为什么我不能把IList传递给F(IEnumerable)?

时间:2022-09-10 23:52:37

I figured I could pass an IList<ChildClass> as an IEnumerable<ParentClass>, since obviously each object in a ChildType list is also an instance of ParentType. But I'm gettin no love from the compiler. What am I missing?

我认为可以将IList 作为IEnumerable继承类>传递给它,因为显然子类型列表中的每个对象也是ParentType的实例。但是我不喜欢编译器。我缺少什么?

EDIT: Added function Foo3 which does what I want. Thanks!

编辑:添加了函数Foo3,这是我想要的。谢谢!

namespace *
{
    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);
        }
    }
}

5 个解决方案

#1


5  

Because generics aren't co/contra variant:

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

Eric Lippert's blog has a great post on this.

Eric Lippert的博客上有一篇关于这方面的文章。

Another article from Charlie Calvert is here.

Charlie Calvert的另一篇文章在这里。

#2


2  

You're missing generic variance, which doesn't exist in C# at the moment. Your code would work in C# 4.0, I believe.

您正在丢失泛型方差,这在c#中是不存在的。我相信您的代码在c# 4.0中可以工作。

This is a duplicate of other questions though...

这是其他问题的重复……

See:

看到的:

#3


1  

You should find all you're looking for in Eric Lippert's Covariance and Contravariance series. It's a fair bit of reading, but answers (a) why you can't do this in C# 3.0, and (b) why you will be able to do it i C# 4.0.

你应该在Eric Lippert的协方差和逆变级数中找到你要找的所有东西。这是一个很好的阅读材料,但是回答(a)为什么你不能在c# 3.0中这样做,(b)为什么你可以在c# 4.0中这样做。

#4


0  

I'm afraid there's no implicit casting to generic parameter types (no "generic variance" seems to be the technical term). Not sure I could give you a deeper explanation, but I would just accept it as the way the CLR works...

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

You'll simply need to use the Cast extension method on childClassList to cast the list to IEnumerable.

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

#5


0  

While in the case of IList and IEnumerable things would work out OK, the compiler has no way of really knowing that when you see it as collection and collection.

虽然对于IList和IEnumerable来说是可以的,但是当您将其视为集合和集合时,编译器无法真正地知道这一点。

If you could use a collection as a collection somebody could try add a Parent to the collection ... the compiler has to prevent this.

如果你可以使用一个集合作为一个集合,有人可以尝试添加一个父元素到集合中……编译器必须防止这种情况。

#1


5  

Because generics aren't co/contra variant:

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

Eric Lippert's blog has a great post on this.

Eric Lippert的博客上有一篇关于这方面的文章。

Another article from Charlie Calvert is here.

Charlie Calvert的另一篇文章在这里。

#2


2  

You're missing generic variance, which doesn't exist in C# at the moment. Your code would work in C# 4.0, I believe.

您正在丢失泛型方差,这在c#中是不存在的。我相信您的代码在c# 4.0中可以工作。

This is a duplicate of other questions though...

这是其他问题的重复……

See:

看到的:

#3


1  

You should find all you're looking for in Eric Lippert's Covariance and Contravariance series. It's a fair bit of reading, but answers (a) why you can't do this in C# 3.0, and (b) why you will be able to do it i C# 4.0.

你应该在Eric Lippert的协方差和逆变级数中找到你要找的所有东西。这是一个很好的阅读材料,但是回答(a)为什么你不能在c# 3.0中这样做,(b)为什么你可以在c# 4.0中这样做。

#4


0  

I'm afraid there's no implicit casting to generic parameter types (no "generic variance" seems to be the technical term). Not sure I could give you a deeper explanation, but I would just accept it as the way the CLR works...

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

You'll simply need to use the Cast extension method on childClassList to cast the list to IEnumerable.

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

#5


0  

While in the case of IList and IEnumerable things would work out OK, the compiler has no way of really knowing that when you see it as collection and collection.

虽然对于IList和IEnumerable来说是可以的,但是当您将其视为集合和集合时,编译器无法真正地知道这一点。

If you could use a collection as a collection somebody could try add a Parent to the collection ... the compiler has to prevent this.

如果你可以使用一个集合作为一个集合,有人可以尝试添加一个父元素到集合中……编译器必须防止这种情况。