Goal
I have a generic class GenericClass<T>
and I want to pool instances.
I'm interested in seeing if I can get the syntax:
MyGenericPool = new GenericPool<GenericClass>();
// Or maybe it's MyGenericPool = new GenericPool<GenericClass<>>();
GenericClass<TGenericParam> GenericClassInstance =
MyGenericPool.Get<TGenericParam>();
(My understanding of generics says, no I can't, don't be silly the syntax doesn't exist / wouldn't work, but I'm intested in what others think).
Showing my workings
I'm a bit doubtful as from my understanding the types GenericClass<string>
and GenericClass<int>
aren't really related from the type system's point of view.
Now, I realise that I can get close, i.e.:
GenericClass<TGenericParam> GenericClassInstance =
GenericPool.Get<GenericClass<TGenericParam>>();
and then have the GenericPool
just store a Dictionary<Type, ObjectPool<object>>
somewhere.
I'm interested in seeing if I can avoid having to do that. I don't want to have to specify the generic type every time when, as the caller, i'm only changing the generic type parameter. I'd also like to be able to enforce (compile time) that all objects going into my GenericObjectPool<T>
are of a set generic type (T<>
).
I think the problem stems from not being able to treat a generic type parameter as being generic its self. If I could do that (can I already??) then maybe something like the below might work:
public class GenericClassPool<TGeneric> where TGeneric : class<>
{
private readonly Dictionary<Type, object> objectPools = new Dictionary<Type, object>();
private void EnsureObjectPoolExists<TGenericParam>()
{
if (!objectPools.ContainsKey(typeof(TGenericParam)))
{
objectPools.Add(typeof(TGenericParam), new ObjectPool<TGeneric<TGenericParam>>(() => Activator.CreateInstance(typeof(TGeneric<TGenericParam>)) as TGeneric<TGenericParam>));
}
}
private ObjectPool<TGeneric<TGenericParam>> GetPool<TGenericParam>()
{
EnsureObjectPoolExists<TGenericParam>();
return (objectPools[typeof(TGenericParam)] as ObjectPool<TGeneric<TGenericParam>>);
}
public void Add<TTypeParam>(TGeneric<TGenericParam> obj)
{
EnsureObjectPoolExists<TTypeParam>();
GetPool<TGenericParam>().Add(obj);
}
public TGeneric<TGenericParam> Get<TGenericParam>()
{
return GetPool<TGenericParam>().Get() as TGeneric<TGenericParam>;
}
}
Question
Can I get the syntax I want (at the top)? If not, how close can I get?
The solution / syntax you are trying to achieve doesn't work that way, because you can't use a generic type without its type parameters as the type parameter to another generic type.
However, you could achieve similar results with the following approach:
Something like that:
Usage would then be like this:
The draw back of this solution is that you would need to create one pool class for each generic type you want to pool, so you potentially will have a lot of
<className>Pool
classes deriving fromObjectPool
.To make this usable, all real code needs to be in the
ObjectPool
class and only code that supplies the generic parameters remains in the derived classes.