C# 为什么IEnumerable不需要强制转换,而需要列表?

C# 为什么IEnumerable不需要强制转换,而需要列表?,c#,C#,给出以下LinqPad示例: void Main() { List<DbItem> dbItems = new List<DbItem> { new DbItem{Id = 4, SomeValue = "Value For 4", OtherValue = 1}, new DbItem{Id = 19, SomeValue = "Value For 19", OtherValue = 2} }; L

给出以下LinqPad示例:

void Main()
{   
    List<DbItem> dbItems = new List<DbItem>
    {
        new DbItem{Id = 4, SomeValue = "Value For 4", OtherValue = 1},
        new DbItem{Id = 19, SomeValue = "Value For 19", OtherValue = 2}
    };

    ListMethod(dbItems.Cast<IDbItem>().ToList());   <-+
    EnumerableMethod(dbItems);                      <-+
}                                                     |  
                                                      |
//    These are the methods are I asking about -------+

public void ListMethod(List<IDbItem> dbItems)
{
    Console.WriteLine(dbItems);
}
public void EnumerableMethod(IEnumerable<IDbItem> dbItems)
{
    Console.WriteLine(dbItems);
}
public class DbItem : IDbItem
{
    public int Id {get; set;}
    public string SomeValue {get; set;}
    public int OtherValue {get; set;}
}   
public interface IDbItem 
{
    int Id {get; set;}
    string SomeValue {get; set;}
}
void Main()
{   
List dbItems=新列表
{
新的DbItem{Id=4,SomeValue=“4的值”,OtherValue=1},
新的DbItem{Id=19,SomeValue=“19的值”,OtherValue=2}
};
ListMethod(dbItems.Cast().ToList());签出。他给出了一个解释和一种使代码在没有强制转换的情况下工作的方法。列表不是协变的,但您可以这样更改方法:

public void ListMethod<T>(List<T> dbItems) where T : IDbItem
{
    Console.WriteLine(dbItems);
}

dogs
实际上是一个狗的列表,而不是动物的列表。因此,在其中添加一个
Cat
将是一个问题,特别是会导致编译器错误。

因为您无法将一个x集合强制转换为一个y集合,即使x源于y,因此每个x都是y。请参阅

这就是为什么协变和逆变的概念被添加到语言中

不幸的是,
List
不支持这些功能

我想答案涉及到协方差这个词

是的,您是正确的,
IEnumerable
的类型参数是协变的。因此,您可以使用指定的类型或更派生的任何类型

   public interface IEnumerable<out T> : IEnumerable
公共接口IEnumerable:IEnumerable
其中as
List
type参数不是协变的

public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable
公共类列表:IList、ICollection、,
IList、ICollection、IReadOnlyList、IReadOnlyCollection、IEnumerable、,
数不清

.NET 4.0/C#4.0仅适用于泛型接口和泛型委托声明;它不适用于具体类型(因此它不是List的支持功能,而是所有具体类型的支持功能)我知道狗实际上是一个狗的列表,而不是动物的列表。但是为什么它对IEnumerable有效呢?
IEnumerable
没有
Add
方法,所以不必担心在
dogs
中添加一个
Cat
。协方差是必须明确指定的东西,而制作
list
的人决定至少,出于上述原因,它不应该是协变的。制作
IEnumerable
的人决定它应该是协变的。
out
关键字是否使IEnumerable协变?如果是,为什么?如果不是,那么是什么?是的,out使类型参数协变,为什么?这是C语言设计者的问题
public class List<T> : IList<T>, ICollection<T>, 
    IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, 
    IEnumerable