我有一种情况,我有一个类在其泛型类型参数中接受某个对象类型的实例。布局是这样的:
public abstract BaseClass { ... }
public DiamondClass : BaseClass { ... }
public SilverClass : BaseClass { ... }
public Handler<T> where T : BaseClass { ... }
我希望能够创建一个方法来返回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("...");
}
}
但这不会起作用,因为显然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("...");
}
}
但现在我需要呼叫GetHandler<DiamondClass>
或GetHandler<BaseClass>
。这违背了在不知道类型的情况下,使用一个基于枚举返回正确处理程序的方法的目的。我希望我可以定义一个Type
对象并传递它,例如:
Type objType = typeof(DiamondClass);
var handler = Handler<objType>();
但显然C#不会允许这种愚蠢行为。我已经用了几种不同的方法,我想有一种方法可以做到这一点,但我被难住了。
(实际上,我确实通过返回dynamic
对象来实现这一点,但如果可能的话,我希望避免它,因为它失去了任何类型安全性和Intellisense支持。)
这就是协方差发挥作用的地方,协方差和反方差只在接口和委托上起作用,所以,为了解决您的问题,只需将新接口IHandler
定义为共变量,out
指定类型参数为协变量:
public interface IHandler<out T> where T : BaseClass
{
}
具有协变类型参数的接口使其方法能够返回比类型参数指定的派生类型更多的派生类型
它会起作用的。更多信息在这里