0

I have an interface which runs a query based on the query parameter and the query result

public interface IQueryParam {}
public interface IQueryResult {}

public interface IQuery<in TQueryParam, out TResult>
  where TQueryParam : IQueryParam
  where TResult : IQueryResult
{
    TResult RunQuery(TQueryParam query);
}

public class GetBushCodes : IQuery<GetalBushCodesParam, ReturnBushCode[]>
{
  ReturnBushCode[] RunQuery(GetalBushCodesParam param) { /*TODO*/ }
}

I want any class that inherits from IQuery have the ability to return a single instance of IQueryResult or an IEnumerable or Array of IQueryResult. My current setup won't allow it and the compiler yells at me for GetBushCodes:

The type 'System.Collections.Generic.IEnumerable<App.Domain.Queries.ReturnBushCode>' 
cannot be used as type parameter 'TResult' in the generic type or 
method 'App.Domain.Queries.IQuery<TQueryParam,TResult>'. There is no implicit 
reference conversion from 
'System.Collections.Generic.IEnumerable<App.Domain.Queries.ReturnBushCode>' to 
'App.Domain.Queries.IQueryResult'.

I do not want to use the setup IQueryParam<TResult> where TResult : IQueryResult because that seems to restrictive and I want to try to keep the IQueryResult constraint on the IQuery because GetBushCodes compiles if I get rid of the constraint.

jmzagorski
  • 1,135
  • 18
  • 42
  • Can you split it into two interfaces for `ISingleResultQuery` and `IMultipleResultQuery` and then have a return type of `IEnumerable` for the latter? I don't think what you want is possible since you need to declare the return type as `T` or `IEnumerable` and these are clearly not interchangeable. The other option is to always return an `IEnumerable` that sometiems only has one item. I'd have thought if you are sure at compile time it should only return one though that using a different interface would be reasonable. – Chris Dec 10 '14 at 15:02
  • hmm I really never thought of adding another interface for IQuery. I do have an `IQueryBuilder` and all it does is return an `IQuery` base on the class type. I guess I could make `GetSingleQuery()` and `GetMultipleQuery()` methods on `IQueryBuilder` and then run one method and if it returns null run the other method. Thanks, I will let you know if this is what I do. – jmzagorski Dec 10 '14 at 15:07
  • Why would you need to run one and then the other? I ask because usually when running a query I know if I expect a single result (eg I am querying on a unique field) or zero, one or more (eg because I am doing a search by name and have unknown number of results). Therefore I should always be able to run the correct query and thus know if the return type is `T` or `IEnumerable`. I'll try to find a moment to write up what I mean in case you are just misunderstanding my brief comments and how I would imagine them being implemented. – Chris Dec 10 '14 at 15:13
  • I do not think I will have to do that now. I am just thinking down the road if I have a generic QueryHandler class that handles simple queries with little or no manipulation that can return one or two `TResults` – jmzagorski Dec 10 '14 at 15:16

0 Answers0