将混凝土类型转换为泛型类型? [英] Cast concrete type to generic type?

查看:87
本文介绍了将混凝土类型转换为泛型类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图编译以下代码:

  public class BaseRequest< TResponse> where TResponse:BaseResponse {} 
public class BaseResponse {}
$ b $ public class FooRequest:BaseRequest< FooResponse> {}
public class FooResponse:BaseResponse {}
$ b ...

public TResponse MakeRequest< TResponse>(BaseRequest< TResponse> request)
where TResponse:BaseResponse
{
}

我希望我可以调用 MakeRequest(new FooRequest())并获取返回值为 FooResponse 。被调用者不必知道 FooRequest ,并可以将它传递给另一个处理程序。签名工作正常,但我无法实现 MakeRequest 方法。如果我这样实现它:

  public TResponse MakeRequest< TResponse>(BaseRequest< TResponse> request)
where TResponse: BaseResponse
{
FooRequest fooRequest =请求为FooRequest;
if(fooRequest!= null)//如果我能处理请求,处理它
{
return new FooResponse(...); // ***
}

BarRequest barRequest =请求作为BarRequest;
if(barRequest!= null)
{
return new BarResponse(...);
}

else //否则,将它传递给下一个节点
{
//也许它会处理一个BazRequest,谁知道
返回nextNode.MakeRequest(请求);


但是 *** 行不会编译,因为编译器不知道 FooResponse TResponse 。我知道这是因为它是在 FooRequest 中指定的。有没有办法解决这个问题,而不涉及讨厌的反射(在这种情况下,我宁愿返回 BaseResponse )?



感谢。
$ b 更新:我正在使用泛型来强制执行返回类型,因此调用站点完全知道要发生什么。在这里返回 BaseResponse 会容易得多,但是它将负责确定具体的返回类型给调用者而不是请求处理程序(当然这些知道所有关于打字)。

解决方案

正如我在评论中所说的,我怀疑你做错了。这看起来像是对泛型的滥用。



也就是说,你告诉编译器我知道更多的类型信息比你更多的方式是通过转换。

  var response = new FooResponse(...); 
return(TResponse)(object)response;

转换为对象,然后转换为TResponse告诉编译器我知道有一个标识,拆箱或从响应到TResponse的参考转换。如果你错了,你会在运行时得到一个异常。


I'm trying to compile the following code:

public class BaseRequest<TResponse> where TResponse : BaseResponse {}
public class BaseResponse {}

public class FooRequest : BaseRequest<FooResponse> {}
public class FooResponse : BaseResponse {}

...

public TResponse MakeRequest<TResponse>(BaseRequest<TResponse> request)
     where TResponse : BaseResponse
{
}

I wish I can call MakeRequest(new FooRequest()) and get the returned value as FooResponse. The callee does not have to know about FooRequest and may pass it on to another handler. The signatures worked fine, however I cannot implement the MakeRequest method. If I implement it like:

public TResponse MakeRequest<TResponse>(BaseRequest<TResponse> request)
     where TResponse : BaseResponse
{
    FooRequest fooRequest = request as FooRequest;
    if (fooRequest != null)   // if I can handle the request, handle it
    {
        return new FooResponse(...);   // ***
    }

    BarRequest barRequest = request as BarRequest;
    if (barRequest != null) 
    {
        return new BarResponse(...);  
    }

    else                      // otherwise, pass it on to the next node
    {
        // maybe it will handle a BazRequest, who knows
        return nextNode.MakeRequest(request);
    }
}

But the *** line won't compile because the compiler does not know FooResponse is a TResponse. I know it is because it's specified in FooRequest. Is there any way to work around this without involving nasty Reflection (in which case I'd rather return BaseResponse instead)?

Thanks.

Update: I'm using generics to enforce the return type so the call site knows exactly what to expect. It would be much easier to just return BaseResponse here, but it puts the burden of figuring out the concrete return type to the caller rather than the request handler (which of course knows all about the typing).

解决方案

As I said in my comment, I suspect that you're doing it wrong. This looks like an abuse of generics.

That said, the way you tell the compiler "I know more type information than you do" is by casting.

var response = new FooResponse(...);   
return (TResponse)(object)response;

The cast to object and then to TResponse tells the compiler "I know that there's an identity, unboxing or reference conversion from response to TResponse". If you're wrong, you'll get an exception at runtime.

这篇关于将混凝土类型转换为泛型类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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