IList的使用在C#中的协方差和逆变,这可能吗?(IList using covariance a

2019-09-23 00:02发布

这会是可能的吗? (我没有对2010年,所以我不能尝试一下自己,对不起)

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    public IEnumerator<TOutput> GetEnumerator();
    public void Add(TInput item);
}

public interface IList<T> : IComplexList<T, T>
{
}

如果我得到它的权利,你可以使用它来真正实现在同一界面协方差和逆变。

Answer 1:

不,你不能。 在您的示例IList<T>是不变的。 IList<T>将需要声明in / out为协变/逆变。 这是不可能做到这一点只是继承了一些接口是协变的。



Answer 2:

那么,你的问题是因为现有的稍显混乱IList<T>类型。 但是,下列情况编译:

public interface IComplexList<out TOutput, in TInput> where TOutput : TInput
{
    IEnumerator<TOutput> GetEnumerator();
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

你甚至可以改变它延长IEnumerable<TOutput>

public interface IComplexList<out TOutput, in TInput>
    : IEnumerable<TOutput>
    where TOutput : TInput
{        
    void Add(TInput item);
}

public interface ISimpleList<T> : IComplexList<T, T>
{
}

索引是棘手的,因为你会希望参与不同类型。 你可以这样做:

TOutput Get(int index);
void Set(int index, TInput item);

然后把索引到ISimpleList<T>代替当然...

这并不是让你使用ISimpleList<T> variantly不过,因为你已经基本上被迫TInput = TOutput。

另一种方法是从输出分离出输入:

public interface IReadableList<out T> : IEnumerable<T>
{
    T Get(int index);
}

public interface IWritableList<in T>
{
    void Add(T item);
    void Set(int index, T item);
}

 public interface IMyList<T> : IReadableList<T>, IWritableList<T> {}

然后,你可以写:

public void Foo(IWritableList<string> x) { ... }

IMyList<object> objects = new MyList<object>();
Foo(objects);

反之为IReadableList 。 换句话说,你允许每方方差分别,但你永远不会得到双方方差在一起。



Answer 3:

如果读写属性的实现也被认为是一个只读属性的实现,人们可以通过具有的IList(Of T)已添加列表协变和逆变的有用的形式从IReadableList(出的T)和IAddableList(派生的在T)。 提供这些接口简单地包含该存在于的IList(Of T)已被定义之前,其实现的IList(OF T)将自动地执行这些其他成员代码成员。 不幸的是,IReadableList是协变,那就必须有一个只读的索引器属性; 在IList的读写性能的实现不能被取代。 因此具有的IList(OF T)从一个可用IReadableList(出T)继承将打破的IList(OF T)的所有实现。



文章来源: IList using covariance and contravariance in c#, is this possible?