8

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

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>or GetHandler<BaseClass>。这违背了拥有一个基于枚举返回正确处理程序的方法的目的,而不知道类型。我希望我可以定义一个Type对象并传递它,如下所示:

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

但显然 C# 不允许这种愚蠢行为。我已经采取了几种不同的方式,我想有办法做到这一点,但我很难过。


(实际上,我确实通过返回一个dynamic对象来完成这项工作,但如果可能的话,我想避免它,因为它失去了任何类型安全和 Intellisense 支持。)

4

1 回答 1

10

这就是变发挥作用的地方,协变和逆变仅适用于接口和委托,因此,要解决您的问题,只需将新接口定义IHandler协变out其中指定类型参数是协变的:

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

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

它会起作用的。更多信息在这里

于 2012-09-27T15:50:01.267 回答