c# - 对 IList 和 IEnumerable 使用泛型逆变

标签 c# .net generics

我正在学习 C# 泛型并制作一些用于测试目的的虚拟代码。所以,我正在测试 in Generic Modifier , 指定类型参数是逆变的。

给定以下界面:

public interface IInterfaceTest<in T>
{
    void Method(T value);
    void Method(IList<T> values);
    void Method(IEnumerable<T> values);
}

编译时,我收到错误消息:

[CS1961] Invalid variance: The type parameter 'T' must be invariantly valid on 'IInterfaceTest.Method(IList)'. 'T' is contravariant.

错误仅与行 void Method(IEnumerable<T> values) 有关.如果删除此行,一切正常。

所以我的问题是:为什么我可以使用 IEnumerable 的通用逆变但不适用于 IList ?我是不是忘记了什么?

谢谢。

最佳答案

为什么不允许 IList<T> 的问题已在评论和相关问题中得到解答:IList<T>T 中不变所以一个反变体T 不能在这里使用。

一开始让我困惑的是 Method(IEnumerable<T>)在这里是允许的。奇怪的是,当您使用 T 时,方差“反转”作为另一个泛型类型的类型参数。

想象一下。

public interface ITestInterface<in T>
{
    void Method(IEnumerable<T> e);
    IEnumerable<T> GetMethod(); // illegal
}
public class Animal {}
public class Lion : Animal [}
public class Gnu : Animal {}

ITestInterface<Animal> animals;
ITestInterface<Lion> lions;
ITestInterface<Gnu> gnus;

现在 ITestInterface<in T> 的协方差在T告诉我们你可以做到

lions = animals;

当您调用 lions.Method(e) 时, 你只能提供 IEnumerable<Lion> .所以 Method 的代码只能枚举Lion s,都是所有Animals作为animals.Method()期望。一切都很好。

另一方面,IEnumerable<T> GetMethod()是非法的,因为:

gnus = animals;

是合法的,现在gnu.GetMethod()会返回 IEnumerable<Animal>你期望 IEnumerable<Gnu> 的地方.当您迭代时,令人惊讶的动物会按顺序等待。

关于c# - 对 IList 和 IEnumerable 使用泛型逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46474309/

相关文章:

c# - 如果 body 撞得太快,区域限制会破坏我的物理模拟

c# - DLL 加载时出现 BadImageFormatException 且 Provider 未在本地计算机上注册问题

.net - 确定何时在(非托管)C++ 中加载 .NET

c# - 使用 WPF 窗口的通用基类

c# - 泛型类装饰器的copy方法如何实现?

java - 为什么不能用 Java 实现泛型数组?

c# - 仅显示枚举的部分选项

c# - 异步等待数据改变

c# - 如何使用异步执行回调委托(delegate)

.net - VB.Net 片段 - 获取函数或子名称