不知道类型就返回通用

KCh*_*oux 7 c# generics inheritance types factory

我有一种情况,我有一个类,在其泛型类型参数中接受某个对象类型的实例.布局是这样的:

public abstract BaseClass { ... }
public DiamondClass : BaseClass { ... }
public SilverClass : BaseClass { ... }

public Handler<T> where T : BaseClass { ... }
Run Code Online (Sandbox Code Playgroud)

我希望能够创建一个方法来返回输入时定义Handler<DiamondClass>Handler<BaseClass>不定义类型的实例.我试过这些方面的东西:

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("...");
    }
}
Run Code Online (Sandbox Code Playgroud)

但这不起作用,因为显然Handler<DiamondClass>不会隐含地施放Handler<BaseClass>.我可以这样指定:

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("...");
    }
}
Run Code Online (Sandbox Code Playgroud)

但现在我需要打电话GetHandler<DiamondClass>GetHandler<BaseClass>.这就违背了一个方法,即在不知道类型的情况下返回基于枚举的正确处理程序的目的.我希望我可以定义一个Type对象并传递它,如下:

 Type objType = typeof(DiamondClass);
 var handler = Handler<objType>();
Run Code Online (Sandbox Code Playgroud)

但显然C#不会允许那种愚蠢.我已经走了几个不同的方式,我想有办法做到这一点,但我很难过.


(实际上我确实通过返回一个dynamic对象来实现这个功能,但是如果可能的话,我想避免使用它,因为它会丢失任何类型的安全性和Intellisense支持.)

cuo*_*gle 9

这是协方差进场时,协方差和反方差仅仅只在接口和委托的工作,所以,要解决你的问题,只是定义一个新的接口IHandler作为共同变异out指定类型参数是协变:

public interface IHandler<out T> where T : BaseClass 
{
}
Run Code Online (Sandbox Code Playgroud)

具有协变类型参数的接口使其方法能够返回比type参数指定的类型更多的派生类型

它会工作.更多信息在这里