对约束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,因为在编译时不知道该类型,因此编译器无法确定超类是什么。 我意识到,乍一看,编译器可以弄清楚
另外,Bar中存在逻辑问题。 你不能调用base.Bar,因为这是一个抽象类型。 为了纠正这个问题,你必须将你在Foo中的实现改为
public virtual void Bar() {}
因为Foo是一种抽象类型。
如果您在类中实现了Foo,然后在模板中使用它,那么您可以这样做。
您也可以使用界面来完成我想要做的事情。
编辑:
在第二次考虑你的代码时,没有任何意义。 您需要创建GENERIC类型的基类,然后从中派生以实现您要执行的操作。 这也会让人更有意义……
abstract class Foo { public virtual void Bar(); }