问题描述
这可能更多是协方差/相反的问题。但是我有以下课程:
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)
{
}
}
想法是LocationStore
应该能够接受具有至少从IOutputPort
继承的泛型类型的Response
对象
然后我尝试调用类似于以下内容的函数:
var genericPresenter = new MockPresenter<GenericResponse>();
var store = new LocationStore();
store.DoThing(genericPresenter);
但是编译器抱怨Argument 1: cannot convert from 'MockPresenter<GenericResponse> to 'IOutputPort<Response>'
即使我从IOutputPort
中删除了逆变修饰符,我仍然会遇到相同的错误。我在这里可能会遗漏一些很明显的东西,但是感觉有点卡住了。如何设计我的DoThing
方法以接受可以具有可以从IOutputPort
继承的任何类型的Response
?
将泛型作为类型参数传递给LocationStore
是不可行的,因为同一实例需要能够通过多个不同的输出端口调用DoThing
。
解决方法
简单的解决方案是使DoThing
通用:
public void DoThing<TResponse>(IOutputPort<TResponse> outputPort) where TResponse : Response
{
}
这使它可以编译,并有望提供所需的功能。
关于为什么不允许您的设计,请考虑以下几点:
public class OutputPort<T>: IOutputPort<T>
{
private List<T> _innerList;
public void Handle(T response)
{
_innerList.Add(response);
}
}
现在,如果T
是GenericResponse
,并且您将能够将其投射到IOutputPort<Response>
上,那么您就可以向Response
添加List<GenericResponse>
希望这很清楚为什么不允许这样做。