我知道不可能从泛型类型参数继承,但是在为抽象类型的衍生物实现公共代理时它会很方便:-)
有谁知道为什么这是不可能的?
示例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
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:一些代码来说明如何使用它的示例.考虑以下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");
}
}
Run Code Online (Sandbox Code Playgroud)
和调用代码:
FooProxy<FooX> fooXProxy = new FooProxy<FooX>();
fooXProxy.X = "test X";
fooXProxy.Bar();
FooProxy<FooY> fooYProxy = new FooProxy<FooY>();
fooYProxy.Y = "test Y";
fooYProxy.Bar();
Run Code Online (Sandbox Code Playgroud)
使用FooX和FooY时,将重用FooProxy覆盖Bar()方法中的代码.
编辑:根据Pete OHanlon的回答修改:使Bar()方法成为虚拟.
Meh*_*ari 46
因为你做不到.泛型不是模板.您不应该像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...
}
Run Code Online (Sandbox Code Playgroud)
仅单个IL将在编译时被发射,并在运行时间,JIT编译器将产生一个单一的所有引用类型的类型参数的本机代码.这与C++模板完全不同,其中本机代码将单独发出T(它受到优化,但从概念上讲,它们是完全独立的代码片段).
您不能从泛型类型参数继承,因为在编译时不知道该类型,因此编译器无法确定超类是什么.我意识到,乍一看,编译器可以弄清楚<T>是什么的事实似乎表明它应该能够弄清楚T是什么,但两者是不同的.
另外,Bar中存在逻辑问题.你不能调用base.Bar,因为这是一个抽象类型.为了纠正这个问题,您必须将Foo中的实现更改为
public virtual void Bar() {}
Run Code Online (Sandbox Code Playgroud)