给出以下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;}
}
为什么EnumerableMethod
可以在ListMethod
首先需要演员时直接获取列表?
我得到一个演员从DbItem发生到IDbItem,但IEnumerable有什么不同允许它在没有明确请求的情况下进行演员?
我认为答案涉及Covariance这个词,但我对此并不了解,只能自己解决。
答案 0 :(得分:4)
结帐this post about covariance。他提供了一个解释和一种方法,使代码可以在没有演员的情况下工作。列表不是协变的,但您可以像这样更改方法:
public void ListMethod<T>(List<T> dbItems) where T : IDbItem
{
Console.WriteLine(dbItems);
}
协方差是指将更多派生的泛型类型分配给基本泛型类型的能力。 List
不协变的原因是因为你可以这样做:
class Animal {}
class Dog : Animal {}
class Cat : Animal {}
void someFunction()
{
List<Animal> dogs = new List<Dog>();
dogs.Add(new Cat());
}
dogs
真的是一个狗的名单,而不是动物。因此,向它添加Cat
将是一个问题,特别是导致编译器错误。
答案 1 :(得分:3)
我想这个答案涉及Covariance这个词
是的,你是对的,IEnumerable<T>
的类型参数是协变的。所以你可以使用你指定的类型或更多派生的类型
public interface IEnumerable<out T> : IEnumerable
List<T>
类型参数不协变的地方
public class List<T> : IList<T>, ICollection<T>,
IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>,
IEnumerable
答案 2 :(得分:0)