为什么以下不编译? (涉及c#中的generics和inheritance)

这编译:

  class ReplicatedBaseType { } class NewType: ReplicatedBaseType { } class Document { ReplicatedBaseType BaseObject; Document() { BaseObject = new NewType(); } } 

但这不是:

  class DalBase : where T: ReplicatedBaseType { } class DocumentTemplate { DalBase BaseCollection; DocumentTemplate () { BaseCollection= new DalBase(); // Error in this line. It seems this is not possible } } 

什么原因?

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

 class DalBase : IEnumerable where T: ReplicatedBaseType { public IEnumerator GetEnumerator() {throw new NotImplementedException();} IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); } } class DocumentTemplate { IEnumerable BaseCollection; DocumentTemplate() { BaseCollection = new DalBase(); // Error in this line. It seems this is not possible } } 

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

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

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

为了进入最后一点,假设DalBase有这种方法:

 void AddEntity(T entity) 

现在你已经有了这样的东西你想要编译 – 但显然是危险的:

 DalBase fruitDal = new DalBase(); fruitDal.AddEntity(new Apple()); 

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

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

它不起作用,因为DalBase不是DalBase – generics没有co / contra-variance。 在C#4中,您可以获得generics差异,但仅限于接口和委托。

您想要的function称为“协方差”,仅在C#4.0中引入http://blog.tlk.com/dot-net/2009/c-sharp-4-covariance-and-contravariance

您的代码失败,因为没有这样的强制转换(显式和隐式)。 C#(<= 3.0)的当前规则禁止它。

检查可能的演员表见§6.1.6C#规范

此代码在VS2010中编译,net framework 4

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class ReplicatedBaseType { } class NewType : ReplicatedBaseType { } class Document { ReplicatedBaseType BaseObject; Document() { BaseObject = new NewType(); } } interface DalBase where T: ReplicatedBaseType { } class DalBaseExample : DalBase where T: ReplicatedBaseType { } class DocumentTemplate { DalBase BaseType; DocumentTemplate () { BaseType = new DalBaseExample(); // no error here } } class Program { static void Main(string[] args) { } } }