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?
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
{
}
Class<T>
where T
is never publicly exposed. Simple, yet so obvious I couldn't see it. :-) It cut out roughly half of the types that need to be forwarded around - Foran 2012-04-04 04:04
T
(methods, properties, events, and fields) that are not type-dependent into interfaces - Chris Shain 2012-04-04 04:19
One option seems to be:
interface IWebService
{
}
interface IClient<out T>
{
}
abstract class BaseClient<T> : IClient<T>
{
}
class SpecializedClient : BaseClient<IWebService>
{
}
class ClientHelper<T> where T : IClient<object>
{
}
However that will only work if you BaseClient
only returns T
and never accepts it.
T
they simply use it internally. I'll take any simplification I can get as it is beginning to become unwieldy - Foran 2012-04-04 03:51