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

标签 c# generics covariance ilist contravariance

这可能吗? (我没有vs.2010,所以没法自己试,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>
{
}

如果我没看错,您可以使用它在同一接口(interface)中实际实现协变和逆变。

最佳答案

嗯,由于现有的 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>虽然有所不同,因为您基本上强制了 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 反之亦然.换句话说,您可以单独允许每一侧的方差,但永远不会同时获得两侧的方差。

关于c# - IList在c#中使用协变和逆变,这可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1259104/

相关文章:

c# - 获取鼠标指针下方的窗口句柄,同时忽略半透明窗口

c# - 重构代码 : When to do what?

c# - 在 Windows 运行时从位图创建流

C# 类型参数作为通用声明

java - 作为映射值的上限通配符 - 如何使用 getOrDefault() 提供默认值

c# - 基于 C# 中的 Type 参数的泛型返回类型

c# - 使用泛型类型接口(interface)创建对象实例时出现编译错误

c# - 创建和使用协变和可变列表(或潜在的解决方法)

javascript - 在 WInRT 应用程序中下载 WebView 内容

c# - 无法转换通用对象