使用IList和IEnumerable的通用逆变量

时间:2017-09-28 16:41:45

标签: 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]方差无效:类型参数“T”必须是不变的   在'IInterfaceTest.Method(IList)'上有效。 'T'是逆变的。

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

所以我的问题是:为什么我可以将通用逆变量与IEnumerable一起使用,但不能与IList一起使用?我忘记了什么吗?

感谢。

1 个答案:

答案 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,其中 所有Animalsanimals.Method()所期望的。一切都很好。

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

gnus = animals;

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