This may be more of a covariance/contravariance issue. But I have the following classes:
public interface IOutputPort<in TUseCaseResponse>
{
void Handle(TUseCaseResponse response);
}
//Abstract parent
public abstract class Response
{
}
//Concrete child
public class GenericResponse : Response
{
}
internal class MockPresenter<TResponse> : IOutputPort<TResponse> where TResponse : Response
{
public void Handle(TResponse response)
{
}
}
public class LocationStore
{
public void DoThing(IOutputPort<Response> outputPort)
{
}
}
The idea is that LocationStore
should be able to accept an IOutputPort
object that has a generic type that at least inherits from Response
I then try to call my function similar to:
var genericPresenter = new MockPresenter<GenericResponse>();
var store = new LocationStore();
store.DoThing(genericPresenter);
But the compiler complains that Argument 1: cannot convert from 'MockPresenter<GenericResponse> to 'IOutputPort<Response>'
Even if I remove the contravariant modifier from IOutputPort
I still get the same error. I might be missing something pretty obvious here, but I'm feeling a bit stuck. How do I design my DoThing
method to accept an IOutputPort
that can have any type inheriting from Response
?
Passing in a generic as a type argument to LocationStore
isn't an option, because the same instance needs to be able to call DoThing
with several different output ports.
Well the easy solution is to just make DoThing
generic:
public void DoThing<TResponse>(IOutputPort<TResponse> outputPort) where TResponse : Response
{
}
This makes it compile, and hopefully provide the functionality you need.
As for why your design was not allowed consider the following:
public class OutputPort<T>: IOutputPort<T>
{
private List<T> _innerList;
public void Handle(T response)
{
_innerList.Add(response);
}
}
Now if T
is GenericResponse
and you would be able to cast it to IOutputPort<Response>
suddenly you would be able to add a Response
to the List<GenericResponse>
which hopefully is clear why it isn't allowed.