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.
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.