为什么以下不编译? (涉及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) { } } }