IList using covariance and contravariance in c#, is this possible?

依然范特西╮ 提交于 2020-02-03 05:17:45

问题


would this be possible? (I don't have vs. 2010, so I can't try it myself, sorry)

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>
{
}

If I get it right, you could use this to actually implement covariance and contravariance in the same interface.


回答1:


No, you can't. In your example IList<T> is invariant. IList<T> would require to declare in/out to be covariant/contravariant. It's not possible to do that just by inheriting some interface that is covariant.




回答2:


Well, your question is slightly confusing because of the existing IList<T> type. However, the following does compile:

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

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

You can even change it to extend 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>
{
}

The indexer is tricky, because you'd want different types involved. You could do:

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

and then put the indexer into ISimpleList<T> instead of course...

That doesn't let you use ISimpleList<T> variantly though, because you've basically forced TInput=TOutput.

An alternative approach is to separate out the input from the output:

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> {}

Then you could write:

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

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

and vice versa for IReadableList. In other words, you allow variance for each side individually, but you never get variance for the two sides together.




回答3:


If an implementation of a read-write property were also considered an implementation of a read-only property, one could add a useful form of List covariance and contravariance by having IList(of T) derive from IReadableList(of Out T) and IAddableList(of In T). Provided that those interfaces simply included members that were present in IList(Of T) before they were defined, code which implemented IList(Of T) would automatically implement those other members. Unfortunately, for IReadableList to be covariant, it would have to have a read-only indexer property; the implementation of the read-write property in IList could not be substituted. Having IList(Of T) inherit from a usable IReadableList(Of Out T) would thus break all implementations of IList(Of T).



来源:https://stackoverflow.com/questions/1259104/ilist-using-covariance-and-contravariance-in-c-is-this-possible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!