Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic inherited type restriction in C#

I have an inelegant solution for what I need, but am looking for an elegant solution to replace it.

The following code doesn't compile, but represents what I would like to do:

interface IWebService
{
}

abstract class BaseClient<T>
{
}

class SpecializedClient : BaseClient<IWebService>
{
}

class ClientHelper<T> where T : BaseClient<*>
{
}

Where the T in ClientHelper<T> is any class that extends BaseClient regardless of the templated type passed in.

The inelegant solution I found is:

class ClientHelper<T, U> where T : BaseClient<U> {}

The reason this becomes inelegant is my project ends up with a class similar to:

class MyClass<A, B, C, D, E, F, G> where A  : MyBaseClass<B, C, D, E, F, G>

All the way down to the base class that takes a single type. Is this simply the cost of having a complex inheritance tree of generic classes or is there a simpler way to do this while retaining type restrictions on the templated types?

like image 504
Foran Avatar asked Apr 04 '12 03:04

Foran


People also ask

Can generic types 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.

What is generic type constraint?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)

Is generic type safe in C#?

Generics in C# is its most powerful feature. It allows you to define the type-safe data structures. This out-turn in a remarkable performance boost and high-grade code, because it helps to reuse data processing algorithms without replicating type-specific code.


1 Answers

Your "inelegant" solution is the right one if the public interface of BaseClient exposes it's generic type parameter in any way.

So assuming BaseClient is not as you defined it:

abstract class BaseClient<T>
{
   //Something about T here
}

Then T is part of the public interface contract of BaseClient, and therefore part of the public interface contract of ClientHelper (again, assuming that BaseClient<U> is exposed via the interface of ClientHelper).

On the other hand, let's assume it actually is as your example puts it:

abstract class BaseClient<T>
{
   //Nothing about T here
}

In that case, you can do:

interface IBaseClient
{
   //Nothing about T here
}

abstract class BaseClient<T> : IBaseClient
{ 
    // Whatever you like here
}

and ClientHelper becomes:

class ClientHelper<T> where T : IBaseClient
{
}
like image 147
Chris Shain Avatar answered Sep 28 '22 22:09

Chris Shain