tags:

views:

60

answers:

2

I may well be missing something obvious here; but if I have the following:

public interface IRequest<out T>
    where T : class 
{
    T Request
    {
        get;
    }
}

And:

public interface IResponse<out T>
    where T : class 
{
    T Response
    {
        get;
    }
}

And then a third interface which uses these interfaces as generic type parameters:

public interface IResponder<in TRequest, TRequestValue, out TResponse, TResponseValue>
    where TRequest : IRequest<TRequestValue>
    where TResponse : IResponse<TResponseValue>
    where TRequestValue : class 
    where TResponseValue : class
{
    TResponse Query(TRequest request);
}

Is there a way to avoid having to pass through TRequestValue and TResponseValue as generic parameters to IResponder (and therefore avoid having to duplicate the associated constraints)?

Essentially I'd prefer to have something similar to the following to reduce the number of generic type parameters to IResponder (I realise this wouldn't compile at the moment):

public interface IResponder<in TRequest, out TResponse>
    where TRequest : IRequest
    where TResponse : IResponse
{
    TResponse Query(TRequest request);
}

The only way I can think of doing this would be to write two non-generic interfaces (IRequest and IResponse) and then make IRequest<T> and IResponse<T> implement those, but that seems wrong in some way.

I'm fully aware that I may have hit this problem because of the way I'm doing things here, so please feel free to suggest what I'm doing wrong!

Note: The whole Request, Response, Responder example isn't actually the code I'm writing, but rather an example to try and support my question.

A: 

No. It is not necessarily true that IRequest will be in terms of IRequestValue. It's clear to you, but that's only because of abstract semantics. The compiler can't know that.

Consider also if you took the same approach with function parameters. Would it be reasonable to assume that tramp arguments could be inferred by the compiler? No. You have to pass them along manually and there's no way around it.

siride
+1  A: 

Your idea of creating separate non-generic interfaces is actually the usual way in C# of accommodating non-generic scenarios. (see IList<T> and IList, for example) IMO, there's a good chance that generics is not going to add much value at all in your situation. It looks like you're using them to constrain how people use your classes, rather than trying to actually get re-use and simplify your code. My suggestion would be to go with the non-generic IRequest and IResponse interfaces and simply have Responder use those directly without any generics at all. If you really think it's important for the Query method to have the exact right type without having to do any casting, you should go all the way and accept the verbosity of all the type constraints.

Kirk Woll
Cheers Kirk. I think you make a good point; looking again at my design, I don't think there's any burning reason why the two interfaces actually *have* to be generic, so I'm revisiting it as we speak.
Dougc