为什么以下不编译?(涉及c#中的泛型和继承)

vir*_*mic 3 .net c# generics

这编译:

    class ReplicatedBaseType
    {
    }

    class NewType: ReplicatedBaseType
    {
    }

    class Document
    {
    ReplicatedBaseType BaseObject;

    Document()
    {
     BaseObject = new NewType();
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不是:

    class DalBase<T> : where T: ReplicatedBaseType
    {
    }

    class DocumentTemplate
    {
    DalBase<ReplicatedBaseType> BaseCollection;
    DocumentTemplate ()
    {
    BaseCollection= new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
    }
Run Code Online (Sandbox Code Playgroud)

什么原因?

Jon*_*eet 8

正如安德烈所说,你想要(通用)协方差.然而:

  • 通用方差仅在C#4中受支持
  • 类不支持通用方差
  • 在您的现实生活中,这可能是不安全的.

要进入最后一点,假设DalBase<T>有这样的方法:

void AddEntity(T entity)
Run Code Online (Sandbox Code Playgroud)

现在你已经有了这样的东西,你希望能够编译 - 但显然是危险的:

DalBase<Fruit> fruitDal = new DalBase<Banana>();
fruitDal.AddEntity(new Apple());
Run Code Online (Sandbox Code Playgroud)

第二行必须编译 - 所以为了在编译时失败,它必须是第一行失败.

我最近就通用差异进行了一个小时的讨论,如果你想了解更多信息,你可能会觉得有用 - 请参阅NDC 2010视频页面并搜索"差异".另外,您可以阅读Eric Lippert关于该主题的博客文章 - 但请注意,这可能需要一个多小时;)


Mar*_*ell 6

C#4.0目标.NET 4中存在差异,但仅限于in/ out(哦和参考类型数组)的接口和用法.例如,要制作协变序列:

class DalBase<T> : IEnumerable<T> where T: ReplicatedBaseType
{
    public IEnumerator<T> GetEnumerator() {throw new NotImplementedException();}
    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }
}

class DocumentTemplate
{
    IEnumerable<ReplicatedBaseType> BaseCollection;
    DocumentTemplate()
    {
        BaseCollection = new DalBase<NewType>(); // Error in this line. It seems this is not possible
    }
}
Run Code Online (Sandbox Code Playgroud)

但除此之外......不.坚持使用非通用列表(IList),或使用预期的列表类型.