Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance on a constrained generic type parameter

Tags:

c#

generics

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#:

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:

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.

EDIT: Revised as per Pete OHanlon's answer: made Bar() method virtual.

like image 326
VirtualStaticVoid Avatar asked Sep 14 '09 09:09

VirtualStaticVoid


People also ask

Can generic class be inherited?

You cannot inherit a generic type. // class Derived20 : T {}// NO!

Can generic classes be constrained?

You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter. The code below constrains a class to an interface.

What is generic type constraint?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.

Which of the following generic constraints restricts the generic type parameter to an object of the class?

Value type constraint If we declare the generic class using the following code then we will get a compile-time error if we try to substitute a reference type for the type parameter.


1 Answers

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.

The C# specification explicitly prohibits usage of type parameters as base class:

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).

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 library could benefit from it. The problem is, C++ templates are compile time "find and replace" constructs while C# generics are a run time thing.

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. 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).

like image 130
mmx Avatar answered Sep 19 '22 18:09

mmx