I apologize for the confusing title, I'm not quite sure how to word my issue concisely. Here, I have a class structure that does not compile.
class MyEvent
{ }
class EventA : MyEvent
{ }
class EventB : MyEvent
{ }
class MyEventHandler<T>
where T : MyEvent
{ }
class EventAHandler : MyEventHandler<EventA>
{ }
class EventBHandler : MyEventHandler<EventB>
{ }
/*** Tests ***/
abstract class MyEventHandlerTesterBaseClass<SomeEventHandler>
where SomeEventHandler : MyEventHandler<MyEvent>
{
// Plan to set up handler for the concrete test classes below.
protected SomeEventHandler handler;
}
class EventAHandlerTests : MyEventHandlerTesterBaseClass<EventAHandler>
{ }
class EventBHandlerTests : MyEventHandlerTesterBaseClass<EventBHandler>
{ }
It results in the following error on my class EventAHandlerTests
definition:
The type 'EventAHandler' must be convertible to 'MyEventHandler<MyEvent>' in order to use it as parameter 'SomeEventHandler' in the generic class 'MyEventHandlerTesterBaseClass<SomeEventHandler>'
and similarly for EventBHandlerTests
.
My understanding is that EventAHandler
should be convertible to MyEventHandler<MyEvent>
because EventAHandler
inherits MyEventHandler<EventA>
, and thus EventA
should dynamically bind to MyEvent
.
Am I doing something wrong? Or is this impossible?
The problem is that a generic class of type T cannot be cast to another generic class of type U : T.
For example:
class Foo { }
class Bar : Foo { }
void test()
{
List<Bar> bars;
List<Foo> foos = bars; //does not work!!!
}
In your case, MyEventHandlerTesterBaseClass
expects the generic type to be of MyEventHandler<MyEvent>
but EventAHandler
is of type MyEventHandler<EventA>
and therefor does not work. This can be circumvented by using two generics like so:
abstract class MyEventHandlerTesterBaseClass<THandler, TEvent>
where THandler : MyEventHandler<TEvent>
where TEvent : MyEvent