将抽象类的集合作为函数的参数传递
本文关键字:函数 参数传递 集合 抽象类 | 更新日期: 2023-09-27 18:05:23
我想在函数中传递ICollection<AbstractClass>
作为参数。但是当我用具体类型的集合调用它时Visual Studio会显示错误
方法有一些无效参数
我的功能是:
private void GenerateId(ICollection<BaseEntity> entities)
{
foreach (BaseEntity e in entities)
{
e.Id = _baseDao.GetNextId();
}
}
我的电话是:
GenerateId(entity.TitleAdmRegions);
Type of AdmRegions:
public virtual ICollection<TitleAdmRegion> TitleAdmRegions { get; set; }
和AdmRegion是:
public partial class TitleAdmRegion : BaseEntity
{
//...
}
您必须进行显式强制转换—实际上,不能保证T
的集合(其中T
继承自U
)也是U
的集合。当然,很有可能是,但是……
这种关系被称为协方差——在泛型"调用"中使用更具体的类型而不是其祖先的能力。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>
是协变的。因此,另一种简单的方法是使用IEnumerable<BaseEntity>
作为参数:
private void GenerateId<T>(IEnumerable<T> entities) { ... }
接口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>
。