我正在学习C#泛型并为测试目的制作一些虚拟代码。所以,我正在测试in Generic Modifier,它指定类型参数是逆变的。
鉴于以下界面:
public interface IInterfaceTest<in T>
{
void Method(T value);
void Method(IList<T> values);
void Method(IEnumerable<T> values);
}
编译时,我收到错误消息:
[CS1961]方差无效:类型参数“T”必须是不变的 在'IInterfaceTest.Method(IList)'上有效。 'T'是逆变的。
错误仅与行void Method(IEnumerable<T> values)
有关。如果删除此行,则一切正常。
所以我的问题是:为什么我可以将通用逆变量与IEnumerable
一起使用,但不能与IList
一起使用?我忘记了什么吗?
感谢。
答案 0 :(得分:4)
已经在评论和关联问题中回答了为什么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>
的地方。当你迭代时,令人惊讶的动物可以按照那个顺序等待。