tags:

views:

196

answers:

3

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.

+10  A: 

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

Mehrdad Afshari
I want the upvote, but I think your on the money, C++ templates aren't C# generics...
Spence
A: 

Because Foo is an abstract type.

If you implemented Foo in a class then used it at the template then you could do that.

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. It would also make a hell of a lot more sense...

abstract class Foo<T>  
{  
    public virtual void Bar();  
}
Spence
+2  A: 

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.

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

public virtual void Bar() {}
Pete OHanlon