views:

134

answers:

5

I would like to implement a generic C# class which looks roughly as follows:

abstract class Foobar<T> : AbstractBase, T
{ ... }

This fails because C# will only allow types after the base class to be interfaces, so next I try this:

abstract class Foobar<T> : AbstractBase, T where T : interface
{ ... }

But then I find that C# does not allow this form of type constraint. Only where T : struct and where T : class are allowed.

How can I dictate that a type parameter must only be an interface type?

+5  A: 

Basically, you can't.

You can make a contstraint to a specific interface, but not a general one for all interfaces. So you can constrain to IEnumerable for example, but not any interface.

What do you need this for anyway?

Øyvind Bråthen
I noticed that all classes deriving from Foobar<T> also end up implementing T. I thought I could perhaps enforce this being the case by moving the `implements Blah` from my derived classes up onto the base class Foobar.
pauldoo
+1  A: 

You can't in simple words.

saurabh
A: 

This fails because C# will only allow types after the base class to be interfaces

This constraint is due to the lack of multiple inheritance in C#. Multiple inheritance can be approximated by the use of interfaces because the overriding methods are explicit. The same way a class can only extend one other class, but can implement multiple interfaces. The trick here is that the implementing class MUST define the body for a method, so that the implementation is specific on which method is called.

Using a where to limit T can be applied to one class, or several interfaces. You can not limit the range to several classes.

Josh Smeaton
+1  A: 

I believe that you misunderstand the meaning of where T : struct and where T : class.

A generic type constraint like this means that T must be a value type or a reference type respectively.

However, the purpose of an interface is to define a contract, which is a totally different concept as compared to value type vs. reference type semantics.

Therefore a restriction like where T : interface would make no sense.

If you want to know more, I would suggest you to read the C# Programming Guide on type constraints:

Constraints on Type Parameters (C# Programming Guide)

0xA3
+2  A: 

The real problem with that code is that you are inheriting from a type parameter.

Trying to compile

abstract class Foobar<T> : T { ... }

will still fail with: error CS0689: Cannot derive from 'T' because it is a type parameter.

I think that this would be perfectly reasonable at least in the case of abstract classes, and I wanted this feature too, but the c# compiler just wont let you do that.

Roald
+1 for mentioning the core of the problem (deriving from type parameters).
Novox