IList在c#中使用协方差和逆变,这可能吗?

Dan*_*ian 6 c# generics ilist covariance contravariance

这有可能吗?(我没有对阵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>
{
}
Run Code Online (Sandbox Code Playgroud)

如果我做对了,你可以用它来实际在同一个界面中实现协方差和逆变.

Jon*_*eet 8

好吧,由于现有的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>
{
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以将其更改为扩展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>
{
}
Run Code Online (Sandbox Code Playgroud)

索引器很棘手,因为你需要涉及不同的类型.你可以这样做:

TOutput Get(int index);
void Set(int index, TInput item);
Run Code Online (Sandbox Code Playgroud)

然后把索引器放进去ISimpleList<T>代替当然......

这不会让你使用ISimpleList<T>变量,因为你基本上强迫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> {}
Run Code Online (Sandbox Code Playgroud)

然后你可以写:

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

IMyList<object> objects = new MyList<object>();
Foo(objects);
Run Code Online (Sandbox Code Playgroud)

反之亦然IReadableList.换句话说,你可以单独允许每一方的差异,但是你永远不会得到双方的差异.


Meh*_*ari 5

不,你不能.在你的例子中IList<T>是不变的.IList<T>需要声明in/ out是协变/逆变.仅通过继承一些协变的接口是不可能做到这一点的.