Vesuvian
Vesuvian

Reputation: 717

Is it possible to constrain generic types to Interface, new()?

I'm trying to create a simple object recycling class

public class ObjectPool<T> where T : class, IRecyclable, new()
{
}

I want to be able to use it with my interface:

public interface ISomeInterface : IRecyclable
{
}

ObjectPool<ISomeInterface> pool = new ObjectPool<ISomeInterface>();

But this yields the error:

error CS0310: The type `ISomeInterface' must have a public parameterless constructor in order to use it as parameter `T' in the generic type or method `ObjectPool<T>'

From what I have read online I know that I can't specify a constructor in an interface.

I have read that you can use reflection instead of "new" to create a new instance, though I'm concerned about the speed of performing this instantiation.

What is the correct way to resolve this situation? Is there a simpler solution that I'm completely overlooking?

Upvotes: 3

Views: 129

Answers (3)

supercat
supercat

Reputation: 81257

You cannot construct an ObjectPool<ISomeInterface>. You could have a generic type MyClass<TT> where T:class,ISomeInterface,new() declare an ObjectPool<TT> within it, and then later on declare variables of type MyClass<SomeClassWhichImplementsISomeInterfaceAndHasADefaultConstructor>, but the compiler can only execute methods for ObjectPool<T> when T is of a particular known class type which meets all the constraints.

Alternatively, you could omit the new constraint and then require that any code which constructs an ObjectPool<T> must pass the constructor (or other method that creates the instance) a Func<T>. That would make it possible to create an ObjectPool<ISomeInterface> provided that one had a method which, when called, would return a new object of some suitable type that implemented ISomeInterface.

Upvotes: 0

Timothy Shields
Timothy Shields

Reputation: 79581

Interfaces can only implement other interfaces.

interface IA : IB, IC
{
    ...
}

A good way to solve your dilemma is to introduce a factory interface as well.

interface IThing
{
    ...
}

interface IThingFactory
{
    IThing Create();
}

Now anything that wants to have the ability to create things should receive an IThingFactory for that purpose.

If you need a generic concept of a factory, you could use something like this:

interface IFactory<T>
{
    T Create();
}

class ObjectPool<T, F>
    where T : IRecyclable        
    where F : IFactory<T>
{
    public ObjectPool(F factory)
    {
        ...
    }
}

Upvotes: 2

Daniel A. White
Daniel A. White

Reputation: 191037

You can't provide an interface there. class and new require it to be a constructable reference type.

Upvotes: 2

Related Questions