我有 2 个课程:
Parent
和Child:Parent
.
当我下一步做:
IMyRepository<Child> _childRepository=new MyRepository<Child>();
IMyRepository<Parent> _repository=childRepository;
我收到错误“Сan't convert source type to target type”。请告诉我为什么这段代码不起作用。
我有 2 个课程:
Parent
和Child:Parent
.
当我下一步做:
IMyRepository<Child> _childRepository=new MyRepository<Child>();
IMyRepository<Parent> _repository=childRepository;
我收到错误“Сan't convert source type to target type”。请告诉我为什么这段代码不起作用。
因为,那么您将能够插入 a new AnotherDifferentChild()
– 这不可能存在于 a 中IList<Child>
。如果您想了解有关详细信息的更多信息,请查找有关Covariance、Convariance和Invariance的文章。
如果你想创建一个新的列表,持有 type 的引用Parent
,你可以使用Cast<T>()
LINQ 中的方法:
IList<Parent> parentList = childList.Cast<Parent>().ToList();
我对强制转换不太了解,但我认为泛型不会对父类型进行隐式强制转换。
但添加
childRepository.Cast<Parent>()
应该使它成为可能,尽管您可能必须为此进行扩展,IEnumerable<T>
这将创建一个新的IMyRepository<T>
试试这个
List<Parent> listOfParent = new List<Child>().Cast<Parent>().ToList();
或者
List<Parent> listOfParent = new List<Child>().ConvertAll(x => (Parent)x);
如果我们使用稍微不同的类名,那么不允许您这样做的原因就会变得很清楚。
考虑这个类层次结构:
public class Mammal
{
}
public class Cat: Mammal
{
public void Meow(){}
}
现在假设您有以下列表:
IList<Cat> cats = new List<Cat>{ new Cat() }
cats[0].Meow(); // All is fine.
现在让我们假设您可以分配cats
给IList<Mammal>
:
IList<Mammal> mammals = cats; // Not allowed, but pretend it is.
mammals.Add(new Mammal());
// Because 'mammals' is referencing 'cats', then adding an element to 'mammals'
// will affect 'cats' too - they are both the same list.
// So now cats has two elements; the first is a Cat and the second is a Mammal.
// So now what happens when we do this?
cats[1].Meow(); // Ask a Mammal to Meow(). Ooopsie!
想象一下,如果你能做这样的事情会发生什么。您可以编写如下代码:
IList<Child> children = new List<Child>();
IList<Parent> parents = children;
parents.Add(new Parent());
请注意,parents
它仍然是对与 相同的对象的引用children
,但是我们设法添加了一个不是 ! 的实例的Child
对象IList<Child>
。
正如另一个答案所提到的,这完全与协方差问题有关(与称为范畴论的数学领域密切相关——如果你有机会看到它会很有趣)。
本质上,如果我们写T-> S
, 对于S
多态到T
的两种类型,例如Parent -> Child
,那么如果泛型保持这种关系,它就是协变的。例如IEnumerable
是一个协变,因为IEnumerable<Object> -> IEnumerable<String>
. 编译器知道这一点,因为您可以将 an 强制IEnumerable<String>
转换为IEnumerable<Object>
.