C# List: why you cannot do `List foo = new List();`

前端 未结 9 979
我在风中等你
我在风中等你 2020-12-02 20:05

If you have an Interface IFoo and a class Bar : IFoo, why can you do the following:

List foo = new List();          


        
相关标签:
9条回答
  • 2020-12-02 20:28

    It is to do with the creation of the List, you have specified the T to be IFoo therefore you cannot instantiate it as a Bar since they are different types, even though Bar supports IFoo.

    0 讨论(0)
  • 2020-12-02 20:32

    The reason is that C# does not support co- and contravariance for generics in C# 3.0 or earlier releases. This is being implemented in C# 4.0, so you'll be able to do the following:

    IEnumerable<IFoo> foo = new List<Bar>();
    

    Note that in C# 4.0, you can cast to IEnumerable<IFoo>, but you won't be be able cast to List<IFoo>. The reason is due to type safety, if you were able to cast a List<Bar> to List<IFoo> you would be able to add other IFoo implementors to the list, breaking type safety.

    For more background on covariance and contravariance in C#, Eric Lippert has a nice blog series.

    0 讨论(0)
  • 2020-12-02 20:32

    Because a list of IFoos can contain some Bars as well, but a list of IFoos is not the same thing as a list of Bars.

    Note that I used English above instead of using C#. I want to highlight that this is not a deep problem; you are just getting confused by the details of the syntax. To understand the answer you need to see beyond the syntax and think about what it actually means.

    A list of IFoos can contain a Bar, because a Bar is an IFoo as well. Here we're talking about the elements of the list. The list is still a list of IFoos. We haven't changed that.

    Now, the list you called foo is still a list of IFoos (more pedantically, foo is declared as a List<IFoo>). It cannot be anything else. In particular, it cannot be made into a list of Bars (List<Bar>). A list of Bar is a completely different object than a list of IFoos.

    0 讨论(0)
提交回复
热议问题