不知道类型返回泛型 [英] Returning generic without knowing type

查看:108
本文介绍了不知道类型返回泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

public Handler< T> T:BaseClass {...}

我想要创建一个返回 Handler< DiamondClass> Handler< BaseClass> 实例的方法,而不用定义输入类型。我已经尝试了以下几行:

  public Handler< BaseClass> GetHandler(HandlerType类型)
{
switch(type)
{
case HandlerType.Diamond:return new Handler< DiamondClass>();
case HandlerType.Silver:return new Handler< SilverClass>();
默认值:抛出新的InvalidOperationException(...);






$ b

但这不起作用,因为显然 Handler< DiamondClass> 不会隐式转换为 Handler< BaseClass> 。我可以像这样指定它:

  public Handler< T> GetHandler< T>(HandlerType type)其中T:BaseClass 
{
switch(type)
{
case HandlerType.Diamond:return(Handler< T>)new Handler< DiamondClass> ;();
case HandlerType.Silver:return(Handler< T>)new Handler< SilverClass>();
默认值:抛出新的InvalidOperationException(...);






$ b现在我需要调用 GetHandler< DiamondClass> GetHandler< BaseClass> 。而且这种方法失去了让方法返回基于枚举的正确处理程序的目的,而不知道类型。我希望我可以定义一个 Type 对象并传递它,如下所示:

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

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






(我实际上通过返回一个动态对象来实现这个工作,但是我想尽可能避免它,因为它失去了任何类型安全和Intellisense支持。)

解决方案

这是协变的作用,协方差和contra-variance只能在接口和委托上工作,所以,要解决你的问题,只需将 IHandler 定义为 co-variant a href =http://msdn.microsoft.com/en-us/library/dd469487.aspx =nofollow> out 它指定类型参数是协变化的:

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

具有协变类型的接口参数使其方法返回的派生类型多于类型参数指定的类型。



它将起作用。更多信息请此处


I have a situation where I have a class that accepts an instance of a certain object type in its generic type parameter. The layout is 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 defining the type upon input. I've tried something along these lines:

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 won't work, because apparently Handler<DiamondClass> won't cast implicitly 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 that defeats the purpose of having a method that returns the proper handler based on an enum, without knowing the type. I hoped that I could define a Type object and pass it, as such:

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

But apparently C# won't allow that kind of foolishness. I've gone about this several different ways, and I'd like to think there's a way to do it, but I'm stumped.


(I actually did get this working by returning a dynamic object, but I'd like to avoid it if at all possible, as it loses any type safety and Intellisense support.)

解决方案

This is where co-variance comes into play, covariance and contra-variance just work only on interface and delegate, so, to solve your problem, just define a new interface IHandler as co-variant with out which specifies that the type parameter is co-variant:

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

An interface that has a covariant type parameter enables its methods to return more derived types than those specified by the type parameter

It will work. More information is here

这篇关于不知道类型返回泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆