[英]Inheritance on a constrained generic type parameter
我知道不可能从泛型类型参数继承,但是在为抽象类型的派生实现通用代理时会很方便的:-)
有人知道为什么这不可能吗?
示例C#:
abstract class Foo
{
public virtual void Bar()
{
// nop
}
}
class FooProxy<TFoo> : 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<FooX> fooXProxy = new FooProxy<FooX>();
fooXProxy.X = "test X";
fooXProxy.Bar();
FooProxy<FooY> fooYProxy = new FooProxy<FooY>();
fooYProxy.Y = "test Y";
fooYProxy.Bar();
使用FooX和FooY时,将重用Bar()方法的FooProxy重写中的代码。
编辑:根据Pete OHanlon的答案进行了修改:使Bar()方法成为虚拟的。
因为你不能。 泛型不是模板。 您不应该像C ++模板那样考虑它们,并且期望它们具有相同的行为。 它们是根本不同的概念。
C#规范明确禁止将类型参数用作基类:
C#3.0语言规范:类型参数(第4.5节)
类型参数不能直接用于声明基类(第10.2.4节)或接口(第13.1.3节)。
我了解您想要做什么及其用途。 这是C ++模板的传统用例。 具体来说,如果可以使用C#泛型来实现,那么Moq
库之类的东西就可以从中受益。 问题是,C ++模板是编译时的“查找和替换”结构,而C#泛型是运行时的东西。
为了证明这一事实,对于本课程:
class Test<T> where T : class {
// whatever contents it might have...
}
仅单个IL将在编译时被发射,并在运行时间,JIT编译器将生成所有引用类型的类型参数的单个本地代码。 这根本不像C ++模板,后者将为每个T
分别发出本机代码(这是经过优化的,但从概念上讲,它们是完全独立的代码段)。
您不能从泛型类型参数继承,因为类型在编译时是未知的,因此编译器无法弄清楚超类是什么。 我意识到,乍一看,编译器可以弄清楚<T>是什么,这似乎表明它应该能够弄清楚T是什么,但是两者是不同的。
另外,您在Bar中遇到逻辑问题。 您不能调用base.Bar,因为这是抽象类型。 为了纠正此问题,您必须将Foo中的实现更改为
public virtual void Bar() {}
因为Foo是抽象类型。
如果您在类中实现了Foo,然后在模板中使用了Foo,则可以这样做。
您也可以使用界面来执行您认为要执行的操作。
编辑:
仔细考虑一下您的代码,这没有任何意义。 您将需要创建GENERIC类型的基类,然后从该基类派生出来以实现您想要的工作。 这也将使地狱更加有意义...
abstract class Foo<T>
{
public virtual void Bar();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.