[英]Using generic contravariant with IList and IEnumerable
I'm learning C# generics and making some dummy code for testing purposes. 我正在学习C#泛型并为测试目的制作一些虚拟代码。 So, I'm testing the in Generic Modifier , which specifies that the type parameter is contravariant. 所以,我正在测试Generic Modifier ,它指定type参数是逆变的。
Given the below interface: 鉴于以下界面:
public interface IInterfaceTest<in T>
{
void Method(T value);
void Method(IList<T> values);
void Method(IEnumerable<T> values);
}
When compiling, I'm getting the error message: 编译时,我收到错误消息:
[CS1961] Invalid variance: The type parameter 'T' must be invariantly valid on 'IInterfaceTest.Method(IList)'. [CS1961]无效方差:类型参数“T”必须在“IInterfaceTest.Method(IList)”上无效有效。 'T' is contravariant. 'T'是逆变的。
The error is related only with the line void Method(IEnumerable<T> values)
. 该错误仅与行void Method(IEnumerable<T> values)
。 If this line is removed, all works fine. 如果删除此行,则一切正常。
So my question is: Why can I use the generic contravariant with IEnumerable
but does not with IList
? 所以我的问题是:为什么我可以使用IEnumerable
的通用逆变,但不能使用IList
? Am I forgot something? 我忘记了什么吗?
Thanks. 谢谢。
The question why it's not allowed for IList<T>
has been answered in the comments and linked questions already: IList<T>
is invariant in T
and so a contra-variant T
cannot be used here whatsoever. 已经在评论和相关问题中回答了为什么不允许IList<T>
问题: IList<T>
在T
是不变的,因此这里不能使用反变量T
What puzzled me at first is the fact that Method(IEnumerable<T>)
is allowed here. 最让我困惑的是这里允许使用Method(IEnumerable<T>)
这一事实。 The strange thing is that variance is "turned around" when you use the T
as a type argument for another generic type . 奇怪的是,当你使用T
作为另一个泛型类型的类型参数时, 方差被“转过来” 。
Imagine this. 想象一下。
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;
Now the contra-variance of ITestInterface<in T>
in T
tells us that you can do 现在的禁忌方差ITestInterface<in T>
在T
告诉我们,你可以做
lions = animals;
And when you call lions.Method(e)
, you can only provide an IEnumerable<Lion>
. 当你打电话给lions.Method(e)
,你只能提供一个IEnumerable<Lion>
。 So the code of Method
can only enumerate Lion
s, which are all Animals
as animals.Method()
expects. 因此, Method
的代码只能枚举Lion
s,它们都是 Animals
作为animals.Method()
期望的。 Everything is fine. 一切都好。
On the other hand, the IEnumerable<T> GetMethod()
is illegal, because: 另一方面, IEnumerable<T> GetMethod()
是非法的,因为:
gnus = animals;
is legal, and now gnu.GetMethod()
would return an IEnumerable<Animal>
where you'd expect an IEnumerable<Gnu>
. 是合法的,现在gnu.GetMethod()
将返回一个IEnumerable<Animal>
,你期望IEnumerable<Gnu>
。 And when you iterated, suprising animals could wait in that sequence. 当你迭代时,令人惊讶的动物可以按照那个顺序等待。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.