不能在界面

时间:2018-01-11 21:45:12

标签: c# generics interface

我遇到了一些接口和共同/逆变问题,我遇到了一些问题。想象一下如下的结构(原谅任何明显的错误,我现在都在移动)

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',它就可以工作。如果我删除了Reader,那么如果我将T设为'out'就行。我需要做两件事,但显然不能!

我是真的很蠢还是我想要的不可能?谢谢!

1 个答案:

答案 0 :(得分:0)

TIMapper中是逆变的,但在IProfileIDelimitedFileReader中是协变的。协变和逆变的定义是不变,这意味着T不允许任何类型的方差;类似于IList。您当前的设置无效。

如果你在所有接口中声明所需的方差,应该明确这个问题(正如你应该做的那样,否则你会得到神秘的错误消息,因为编译器不能做得更好):

interface IDelimitedFileReader<out T> { /*...*/ }
interface IMapper<in T> { /*...*/ }
interface IProfile<out T> { /*...*/ } //at first glance it looks covariant

如果你试图编译它,编译器会给你一个错误的错误。

如果您在TIProfile中声明interface IProfile<T> { //... }不变,那么错误就会消失,代码应该编译,但是你会遇到一个不变的界面。