some confusion with generic types in c#

This is a covariance problem. The real type of handler is QueryHandler, so it is a IQueryHandler<Query, bool>. Of course Query is an IQuery<bool>, but that is the point of covariance.

It is like trying to assign a List<String> to a variable of type List<Object>.

There exists an out keyword that allows you to use the covariance on your IQueryHandler interface as you expect it.

See out for detailed information

EDIT:

As pointed out by Sweeper, you cannot use out on TQuery because it is used as input parameter. The correct solution is to avoid the dependecy of QueryHandler on Query. Isma has shown nicely how it is done.


This code does not work because IQueryHandler is invariant on the TQuery generic parameter. TQuery needs to be covariant in order for handler to be convertible to IQueryHandler<IQuery<T>, T>, but that is impossible, as I will explain later. You could however, make TQuery contravariant, which allows you to convert handler to IQueryHandler<ASubclassOfQuery, T>. TResult can be covariant though. This is the code to do this:

public interface IQueryHandler<in TQuery, out TResult> where TQuery : IQuery<TResult>

See this page for more info about generic variances.

As for why handler is not IQueryHandler<IQuery<T>, T>, let's first suppose that it is, which means this code would compile:

IQueryHandler<IQuery<T>, T> q = handler;
q.Handle(new MyQuery<T>());

where MyQuery is defined like this:

class MyQuery<T> : IQuery<T> {}

However, handler is of runtime type QueryHandler. QueryHandler.Handle only handles Query objects, not MyQuery<T> objects! We have a contradiction, and hence our assumption that handler is a IQueryHandler<IQuery<T>, T> must be false.