Return generic without knowing type

I have a situation where I have a class that takes an instance of a certain type of object in its typical type parameter. The layout looks something like this:

public abstract BaseClass { ... } public DiamondClass : BaseClass { ... } public SilverClass : BaseClass { ... } public Handler<T> where T : BaseClass { ... } 

I want to be able to create a method to return an instance of Handler<DiamondClass> or Handler<BaseClass> without specifying an input type. I tried something in this direction:

 public Handler<BaseClass> GetHandler(HandlerType type) { switch(type) { case HandlerType.Diamond: return new Handler<DiamondClass>(); case HandlerType.Silver: return new Handler<SilverClass>(); default: throw new InvalidOperationException("..."); } } 

But this will not work, because apparently Handler<DiamondClass> will not implicitly point to Handler<BaseClass> . I can specify it like this:

 public Handler<T> GetHandler<T>(HandlerType type) where T : BaseClass { switch(type) { case HandlerType.Diamond: return (Handler<T>)new Handler<DiamondClass>(); case HandlerType.Silver: return (Handler<T>)new Handler<SilverClass>(); default: throw new InvalidOperationException("..."); } } 

But now I need to call GetHandler<DiamondClass> or GetHandler<BaseClass> . And this defeats the goal of having a method that returns the correct handler based on the enumeration, not knowing the type. I was hoping I could define a Type object and pass it as such:

  Type objType = typeof(DiamondClass); var handler = Handler<objType>(); 

But, apparently, C # will not allow such stupidity. I have done several different ways, and I would like to think that there is a way to do this, but I'm at a dead end.


(I actually got this by returning a dynamic object, but I would like to avoid it, if at all possible, since it loses any type of security and Intellisense support.)

+7
source share
1 answer

This is where covariance, covariance and contradiction arise, only work on the interface and delegation, therefore, to solve your problem, simply define the new IHandler interface as a co-variant with out , which indicates that the type parameter is a co-variant:

 public interface IHandler<out T> where T : BaseClass { } 

An interface with a covariant type parameter allows its methods to return more derived types than those specified by the type parameter

That will work. More info here

+9
source

All Articles