为什么我需要在泛型子类中重新声明类型约束

时间:2011-01-08 16:59:48

标签: c# generics inheritance type-constraints

最近,我尝试通过实现通用接口来创建通用子类。

public interface IModule<T> where T : DataBean { ..... }
public class Module<T> : IModule<T> where T : DataBean { .... } 

似乎我不能依赖于基本界面中定义的任何T限制, 我需要自己重新申报。

MSDN刚提供:

  

使用子类泛型类型时   参数,你必须重复任何   基地规定的限制   子类级别的类级别。对于   例如,推导约束

为什么不能从基类/接口推断出约束?

3 个答案:

答案 0 :(得分:6)

我无法想出c#理论上无法复制约束的任何理由。但是,使我们明确地复制(或扩充)它们的记录行为似乎是最简单的可用性方式。

public class A{}
public class B : A {}

public class X<T> where T: A {}
public class Y<T> : X<T> where T: B { }

在上文中,请注意我没有对Y<T>上的约束进行明确的复制,因为B 总是 A。< / p>

现在让我们看看如果“编译器自动复制约束”会发生什么。假设我在没有约束的情况下定义Y<T>,编译器会自动放置它们。我在很多代码中使用Y<T>。然后我更改X<T>声明的约束以包含一些新接口。

更改X<T>声明的编译器错误位于我使用 Y<T>的网站上!

通过c#编译器当前的工作方式,编译器错误处于X<T>的用法,正如我所期望的那样,如果我以突破方式更改它。

因此,虽然在某些情况下它会很方便,但在其他情况下也会有些混乱。虽然两者都是有效的方法,但我会假设(注意我无法读懂c#设计团队的思想)它是一个判断调用,而不是纯粹的技术调用。

我说“不是纯粹技术性的”,但我可以想象一些界面场景,其中验证是否满足所有约束会更简单,而不是产生满足所有必需的继承约束的最简单约束。

答案 1 :(得分:5)

标准C#团队智慧。声明应该是自我记录的。最重要的是,一种类型声明的更改不应该在不生成诊断的情况下改变不相关的其他类型的行为。设计中的-100点原则是另一种观点。

答案 2 :(得分:1)

接口上的constranints太过分,无法告诉编译器Module类应该具有哪些约束。例如,Module类可能对DataBean的超类(继承类)有约束。

我不知道C#设计师的智慧。因为约束可能不同,我认为决定让开发人员明确声明约束而不是让编译器做出假设。