对约束generics类型参数的inheritance

我知道不可能从generics类型参数inheritance,但是当为抽象类型的衍生物实现公共代理时它会很方便:-)

有谁知道为什么这是不可能的?

示例C#:

abstract class Foo { public virtual void Bar() { // nop } } class FooProxy : TFoo where TFoo : Foo { public override void Bar() { // do some stuff before base.Bar(); // do some stuff after } } 

编辑:一些代码来说明如何使用它的示例。 考虑Foo的以下衍生物:

 class FooX : Foo { public string X { get; set; } public override void Bar() { Console.WriteLine("Doing Bar X"); } } class FooY : Foo { public string Y { get; set; } public override void Bar() { Console.WriteLine("Doing Bar Y"); } } 

和调用代码:

 FooProxy fooXProxy = new FooProxy(); fooXProxy.X = "test X"; fooXProxy.Bar(); FooProxy fooYProxy = new FooProxy(); fooYProxy.Y = "test Y"; fooYProxy.Bar(); 

使用FooX和FooY时,将重用FooProxy覆盖Bar()方法中的代码。

编辑:根据Pete OHanlon的回答修改:使Bar()方法成为虚拟。

因为你做不到。 generics不是模板。 您不应该像C ++模板那样考虑它们并期望相同的行为。 它们是根本不同的概念。

C#规范明确禁止使用类型参数作为基类:

C#3.0语言规范:类型参数(§4.5)

类型参数不能直接用于声明基类(第10.2.4节)或接口(第13.1.3节)。

更新:

我明白你想做什么和它的用途。 这是C ++模板的传统用例。 具体来说,如果可以使用C#generics, Moq库之类的东西可以从中受益。 问题是,C ++模板是编译时“查找和替换”构造,而C#generics是运行时的东西。

为了certificate这个事实,对于这个类:

 class Test where T : class { // whatever contents it might have... } 

在编译时和运行时只会发出一个IL,JIT编译器会为所有引用类型参数生成一个本机代码。 这与C ++模板完全不同,其中本地代码将分别为每个T发出(它受到优化,但从概念上讲,它们是完全独立的代码片段)。

您不能从generics类型参数inheritance,因为在编译时不知道该类型,因此编译器无法确定超类是什么。 我意识到,乍一看,编译器可以弄清楚是什么的事实似乎表明它应该能够弄清楚T是什么,但两者是不同的。

另外,Bar中存在逻辑问题。 你不能调用base.Bar,因为这是一个抽象类型。 为了纠正这个问题,你必须将你在Foo中的实现改为

 public virtual void Bar() {} 

因为Foo是一种抽象类型。

如果您在类中实现了Foo,然后在模板中使用它,那么您可以这样做。

您也可以使用界面来完成我想要做的事情。

编辑:

在第二次考虑你的代码时,没有任何意义。 您需要创建GENERIC类型的基类,然后从中派生以实现您要执行的操作。 这也会让人更有意义……

 abstract class Foo { public virtual void Bar(); }