【问题标题】:Contra/covariance and nested generics反/协方差和嵌套泛型
【发布时间】:2021-01-05 02:41:07
【问题描述】:

我有一个关于打字和 contra/covairance 的问题。

给定以下类

public class BoardItemsHolderRepository<THolder, TBoardItem> : DataRepository<IList<THolder>> 
    where TBoardItem : BoardItem
    where THolder : IBoardItemHolder<TBoardItem>
{
}
public interface IDataRepository<T> : IDataGetRepository<T>, IDataSetRepository<T> where T : class
{
}

public interface IDataGetRepository<out T> where T : class
{
    IObservable<T> GetObservableStream();
    IObservable<T> GetMostRecent();
}

public interface IDataSetRepository<in T> where T : class
{
    void Set(T value);
}

public abstract class DataRepository<T> : IDataRepository<T> where T : class
{
  ..implementation details
}
public class ConstructHolder : IBoardItemHolder<Construct>
{
  ..implementation details
}

鉴于以上 3 个文件,有人可以向我解释为什么会发生以下情况吗?:

IDataGetRepository<IList<IBoardItemHolder<Construct>>> wontCompile = new BoardItemsHolderRepository<ConstructHolder, Construct>(); //illegal
IDataGetRepository<IList<ConstructHolder>> compile = new BoardItemsHolderRepository<ConstructHolder, Construct>();  //legal

我不明白为什么第一行的隐式转换不起作用,因为下面的行编译(如预期)

IBoardItemHolder<Construct>> compile = new ConstructHolder();

【问题讨论】:

    标签: c# generics covariance contravariance strong-typing


    【解决方案1】:

    让我们逐步扩展非法行的右侧。首先,我们从

    BoardItemsHolderRepository<ConstructHolder, Construct>
    

    这是DataRepository&lt;IList&lt;THolder&gt;&gt;,所以上面是一种:

    DataRepository<IList<ConstructHolder>>
    

    又是IDataGetRepository&lt;T&gt;,所以上面是一种:

    IDataGetRepository<IList<ConstructHolder>>
    

    IDataGetRepository&lt;T&gt;T 上是协变的。回想一下这意味着什么:如果 UT 的子类型,那么IDataGetRepository&lt;U&gt;IDataGetRepository&lt;T&gt; 的子类型。例如,IDataGetRepository&lt;Cat&gt;IDataGetRepository&lt;Animal&gt; 的子类型,因此可以将前一种类型的实例分配给后一种类型的变量。

    但是,IDataGetRepository&lt;IList&lt;ConstructHolder&gt;&gt; 不是IDataGetRepository&lt;IList&lt;IBoardItemHolder&lt;Construct&gt;&gt;&gt; 的子类型,因此不能分配给它。为什么? 因为IList&lt;ConstructHolder&gt; 不是IList&lt;IBoardItemHolder&lt;Construct&gt;&gt; 的子类型! IList&lt;T&gt;T 上是不变的!

    因此,根据类型检查器的说法,您尝试做的事情违反了类型安全。也许尝试使用IEnumerable 而不是IList

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 2011-02-09
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多