1

I am trying to create a manager for object pools such that I can call a method from my manager in order to retrieve a reserved object in the pool or to create a new object when necessary. The objects to be pooled can vary greatly but must all inherit from a PooledObject class. There should never be any direct instance of the PooledObject class, only classes that extend PooledObject should be instantiated.

The problem is with the second portion, where I need to create a new object. I cannot instantiate a PooledObject as it is abstract, but including a new() constraint to the T generic does not allow Manager to instantiate the dictionary that manages the different PooledObjects. Below is a snippet of my code.

public class Manager{
    private Dictionary<Type, Pool<PooledObject>> _objects;

    public Manager()
    {
        _objects = new Dictionary<Type, Pool<PooledObject>>();
    }
    ...
}

public class Pool<T> where T : PooledObject{
    ...
    public T newObject(){
        ...
        var newT = new T(); // Error on this line
        ...
    }
    ...
}

public abstract class PooledObject{
    ...
}

How do I make it so that my generic T derives from a class that extends PooledObject and is not abstract so I can use the default constructor?

Ryan T.
  • 197
  • 1
  • 15
  • I tried that but my ```Manager``` will throw this error instead: 'PooledObject' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Pool' – Ryan T. Oct 19 '20 at 07:28
  • You'll probably need to use [`Activator.CreateInstance`](https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance?view=netcore-3.1) to instantiate a new object. – MindSwipe Oct 19 '20 at 07:32
  • Try this `var newT = Activator.CreateInstance();` – Voodoo Oct 19 '20 at 07:33
  • 3
    There are lots of possible ways to address this, but the most common I've seen are reflection (`Activator.CreateInstance()`) or inversion of control (i.e. passing a factory method delegate to the pooling object). See duplicates for examples of those and other alternatives. – Peter Duniho Oct 19 '20 at 07:37
  • @PeterDuniho Thank you, I think I will try the inversion of control method. As I understand, there is significant time cost to using reflection, and I am not sure if it would erase the benefits I get from using a pool in the first place. – Ryan T. Oct 19 '20 at 07:57
  • 1
    Yes, I would use the factory delegate myself. That said, in some scenarios you need reflection (i.e. when for whatever reason it's impractical or impossible to require the caller to provide the factory delegate); in those cases, you can address the time cost issue by using reflection to build an `Expression`, and then compiling that into a delegate which is then itself cached. You incur the overhead only once, after that it's as fast as IoC. – Peter Duniho Oct 19 '20 at 08:07

0 Answers0