传递抽象类的集合作为函数中的参数

时间:2014-05-27 07:07:34

标签: c# .net

我想在函数中传递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
{
  //...
}

2 个答案:

答案 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)等方法。我们有那个

  

TitleAdmRegionBaseEntity

但没有协方差, 暗示

  

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>