简体   繁体   English

约束通用类型参数的继承

[英]Inheritance on a constrained generic type parameter

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()方法成为虚拟的。

Because you can't. 因为你不能。 Generics are not templates. 泛型不是模板。 You shouldn't think about them like C++ templates and expect the same behavior. 您不应该像C ++模板那样考虑它们,并且期望它们具有相同的行为。 They are fundamentally different concepts. 它们是根本不同的概念。

The C# specification explicitly prohibits usage of type parameters as base class: C#规范明确禁止将类型参数用作基类:

C# 3.0 Language Specification: Type Parameters (§4.5) C#3.0语言规范:类型参数(第4.5节)

A type parameter cannot be used directly to declare a base class (§10.2.4) or interface (§13.1.3). 类型参数不能直接用于声明基类(第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. 这是C ++模板的传统用例。 Specifically, if this was possible to do using C# generics, things like Moq library could benefit from it. 具体来说,如果可以使用C#泛型来实现,那么Moq库之类的东西就可以从中受益。 The problem is, C++ templates are compile time "find and replace" constructs while C# generics are a run time thing. 问题是,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 single native code for all reference-type type parameters. 仅单个IL将在编译时被发射,并在运行时间,JIT编译器将生成所有引用类型的类型参数的单个本地代码。 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). 这根本不像C ++模板,后者将为每个T分别发出本机代码(这是经过优化的,但从概念上讲,它们是完全独立的代码段)。

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. 另外,您在Bar中遇到逻辑问题。 You can't call base.Bar because this is an abstract type. 您不能调用base.Bar,因为这是抽象类型。 In order to correct this, you'd have to change your implementation in Foo to 为了纠正此问题,您必须将Foo中的实现更改为

public virtual void Bar() {}

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,然后在模板中使用了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 GENERIC type, then derive from that to achieve what you are trying to do. 您将需要创建GENERIC类型的基类,然后从该基类派生出来以实现您想要的工作。 It would also make a hell of a lot more sense... 这也将使地狱更加有意义...

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将不受约束的泛型类型参数传递给受约束的方法 - Passing unconstrained generic type parameter to a constrained method 类型参数继承的通用类型转换 - Generic Type conversion on type parameter inheritance 为什么我不能将&#39;as&#39;用于限制为接口的泛型类型参数? - Why can't I use 'as' with generic type parameter that is constrained to be an interface? 如何使用受约束的泛型类型参数将 class 实例化为派生接口 - How to instantiate a class as the interface that it derives from with constrained generic type parameter 通用类::类型参数 <T> 财产继承 - Generic Class:: Type Parameter <T> Property Inheritance 约束泛型类型参数的逆解 - Contravariance on constrained generic type parameters 将Type转换为Generic约束T - Convert a Type to a Generic constrained T 在类型参数中具有层次结构的约束泛型 - Constrained generics with hierarchy in type parameter 如何使用带有强制转换的泛型参数(限制为整数类型)实现方法? - How can I implement a method with a generic parameter (constrained to an integer type) with a cast? 在通用方法中检查非类约束类型参数的实例是否为null - Checking instance of non-class constrained type parameter for null in generic method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM