我正在学习 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/