我想在函数中传递ICollection<AbstractClass>
作为参数。但是当我用具体类型的集合调用它时,Visual Studio向我显示错误
方法有一些无效的参数
我的功能是:
private void GenerateId(ICollection<BaseEntity> entities)
{
foreach (BaseEntity e in entities)
{
e.Id = _baseDao.GetNextId();
}
}
我的电话是:
GenerateId(entity.TitleAdmRegions);
AdmRegions类型:
public virtual ICollection<TitleAdmRegion> TitleAdmRegions { get; set; }
AdmRegion是:
public partial class TitleAdmRegion : BaseEntity
{
//...
}
答案 0 :(得分:6)
你必须做一个明确的演员 - 实际上,我无法保证T
的集合,其中T
继承自U
也是U
的集合{1}}。当然,它很可能会,但是......
该关系称为协方差 - 在泛型&#34; call&#34;中使用更具体类型的能力。而不是它的祖先。 MSDN在C#中有一篇关于该主题的好文章 - http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
使用泛型,类型安全的方法实际上非常简单:
private void GenerateId<T>(ICollection<T> entities)
where T: BaseEntity
{
foreach (var e in entities)
{
e.Id = _baseDao.GetNextId();
}
}
此外,虽然ICollection<T>
不是协变的,但IEnumerable<T>
是。{1}}。另一种简单的方法是使用IEnumerable<BaseEntity>
作为参数:
private void GenerateId<T>(IEnumerable<T> entities) { ... }
答案 1 :(得分:1)
接口ICollection<T>
在T
中不协变。它不可能是因为类型包含void Add(T item)
等方法。我们有那个
TitleAdmRegion
是BaseEntity
但没有协方差, 不 暗示
你似乎在想。解决方案是切换到其类型参数中协变的接口。您可以使用
ICollection<TitleAdmRegion>
是ICollection<BaseEntity>
IEnumerable<out T>
或IReadOnlyCollection<out T>
。协方差意味着IEnumerable<TitleAdmRegion>
是IEnumerable<BaseEntity>
,而IReadOnlyCollection<TitleAdmRegion>
是IReadOnlyCollection<BaseEntity>
。所以将签名更改为:
private void GenerateId(IEnumerable<BaseEntity> entities) // or IReadOnlyCollection<BaseEntity>, or IReadOnlyList<BaseEntity>, etc.
{
foreach (BaseEntity e in entities)
{
e.Id = _baseDao.GetNextId();
}
}
一切都会好的。
泛型中的协方差(和逆变)是.NET 4.0(2010)中的新增内容。接口IReadOnlyCollection<out T>
是.NET 4.5(2012)中的新增功能。请注意,允许读写的集合(例如List<T>
类和T[]
数组类型)实现IReadOnlyCollection<out T>
。