C# 受约束的泛型类型参数的继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1420581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Inheritance on a constrained generic type parameter
提问by VirtualStaticVoid
I know it isn't possible to inherit from a generic type parameter, but it would be handy when implementing a common proxy for derivatives of an abstract type :-)
我知道不可能从泛型类型参数继承,但是在为抽象类型的派生实现通用代理时会很方便:-)
Does anyone know why this isn't possible?
有谁知道为什么这是不可能的?
Example C#:
示例 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
}
}
EDIT: Some more code to illustrate an example of how this could be used. Consider the following derivatives of Foo:
编辑:一些更多的代码来说明如何使用它的示例。考虑以下 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");
}
}
And the calling code:
和调用代码:
FooProxy<FooX> fooXProxy = new FooProxy<FooX>();
fooXProxy.X = "test X";
fooXProxy.Bar();
FooProxy<FooY> fooYProxy = new FooProxy<FooY>();
fooYProxy.Y = "test Y";
fooYProxy.Bar();
The code in the FooProxy override of Bar() method will be reused when using FooX and FooY.
当使用 FooX 和 FooY 时,将重用 Bar() 方法的 FooProxy 覆盖中的代码。
EDIT: Revised as per Pete OHanlon's answer: made Bar() method virtual.
编辑:根据 Pete OHanlon 的回答进行修改:使 Bar() 方法成为虚拟的。
采纳答案by Mehrdad Afshari
Because you can't. Generics are not templates. You shouldn't think about them like C++ templates and expect the same behavior. They are fundamentally different concepts.
因为你不能。泛型不是模板。您不应该像 C++ 模板一样考虑它们并期望具有相同的行为。它们是根本不同的概念。
The C# specification explicitly prohibits usage of type parameters as base class:
C# 规范明确禁止使用类型参数作为基类:
C# 3.0 Language Specification: Type Parameters (§4.5)
A type parameter cannot be used directly to declare a base class (§10.2.4) or interface (§13.1.3).
C# 3.0 语言规范:类型参数(第 4.5 节)
类型参数不能直接用于声明基类(第 10.2.4 节)或接口(第 13.1.3 节)。
Update:
更新:
I understand what you want to do and its use. This is a traditional use case of C++ templates. Specifically, if this was possible to do using C# generics, things like Moq
librarycould benefit from it. The problem is, C++ templates are compile time "find and replace" constructs while C# generics are a run time thing.
我了解您想要做什么及其用途。这是 C++ 模板的传统用例。具体来说,如果可以使用 C# 泛型来做到这一点,那么Moq
库之类的东西就可以从中受益。问题是,C++ 模板是编译时的“查找和替换”构造,而 C# 泛型是运行时的。
To demonstrate this fact, for this class:
为了证明这一事实,对于这个类:
class Test<T> where T : class {
// whatever contents it might have...
}
only a single IL will be emitted at compile time and at run time, the JIT compiler would generate a singlenative code for all reference-type type parameters. This is not like C++ templates at all, where native code would be emitted for every T
separately (it's subject to optimization but conceptually, they are completely separate pieces of code).
在编译时和运行时只会发出单个 IL,JIT 编译器将为所有引用类型类型参数生成单个本机代码。这根本不像 C++ 模板,其中每个T
单独的本机代码都会被发出(它需要优化,但从概念上讲,它们是完全独立的代码段)。
回答by Spence
Because Foo is an abstract type.
因为 Foo 是一个抽象类型。
If you implemented Foo in a class then used it at the template then you could do that.
如果您在类中实现 Foo 然后在模板中使用它,那么您可以这样做。
You could also use an interface to do what you are trying to do I believe.
我相信您也可以使用界面来做您想做的事情。
Edit:
编辑:
On second thought looking at your code, it makes no sense. You would need to create a base class of the GENERICtype, then derive from that to achieve what you are trying to do. It would also make a hell of a lot more sense...
再想想看你的代码,这是没有意义的。您需要创建一个GENERIC类型的基类,然后从中派生以实现您要执行的操作。这也会更有意义......
abstract class Foo<T>
{
public virtual void Bar();
}
回答by Pete OHanlon
You can't inherit from a generic type parameter because the type isn't known at compile time so the compiler can't figure out what the superclass is. I realise that, at first glance, the fact that the compiler can figure out what <T> is would seem to suggest that it should be able to figure out what T is, but the two things are different.
您不能从泛型类型参数继承,因为该类型在编译时未知,因此编译器无法确定超类是什么。我意识到,乍一看,编译器可以弄清楚 <T> 是什么这一事实似乎表明它应该能够弄清楚 T 是什么,但这两者是不同的。
Also, you have a logic problem in Bar. You can't call base.Bar because this is an abstract type. In order to correct this, you'd have to change your implementation in Foo to
另外,您在 Bar 中存在逻辑问题。你不能调用 base.Bar 因为这是一个抽象类型。为了解决这个问题,您必须将 Foo 中的实现更改为
public virtual void Bar() {}