我在接口和协变/逆变方面遇到了一些问题,我遇到了一些问题。想象一下像下面这样的结构(请原谅任何明显的错误,我现在在移动领域(
public interface IDelimitedFileReader<T>
{
IEnumerable<T> Read(string file);
}
public interface IMapper<T> where T : IManifestItem
{
MappedRecord Map(IEnumerable<T> items);
}
public interface IProfile<T> where T : IManifestItem
{
IDelimitedFileReader<T> Reader { get; }
IMapper<T> Mapper { get; }
}
public class ProfileImpl : IProfile<ManifestItemImpl>
{
IDelimitedFileReader<ManifestItemImpl> Reader => new DelimitedFileReaderImpl<ManifestItemImpl>();
IMapper<ManifestItemImpl> Mapper => new MapperImpl<ManifestItemImpl>();
}
public static class ProfileRetriever
{
public static IProfile<IManifestItem> GetProfile()
{
return new ProfileImpl();
}
}
但是,我的 GetProfile 方法抱怨返回类型不匹配。我相信这是因为 IProfile 接口需要协变和逆变 - 如果我删除接口和实现上的 Mapper 属性,并将 T 更改为 IProfile 中的"in",它可以工作。如果我删除阅读器,如果我使 T "出",它会起作用。我需要同时做这两件事,但显然不能!
我真的是愚蠢还是我想要的不可能?谢谢!
T
在IMapper
中是逆变的,但在IProfile
和IDelimitedFileReader
中是协变的。某物协变和逆变的定义是不变的,这意味着 T 不允许任何类型方差;类似于IList。您当前的设置将不起作用。
如果您在所有接口中声明所需的方差,则应明确该问题(您应该这样做,否则您将收到神秘的错误消息,因为编译器无法做得更好(:
interface IDelimitedFileReader<out T> { /*...*/ }
interface IMapper<in T> { /*...*/ }
interface IProfile<out T> { /*...*/ } //at first glance it looks covariant
如果您尝试编译它,编译器会给您一个精确的错误。
如果你在IProfile
中声明T
不变的:interface IProfile<T> { //... }
那么错误就会消失,代码应该编译,但你坚持使用不变的接口。