c# - 泛型中的 <out T> 与 <T>

标签 c# generics covariance

<out T> 之间有什么区别?和 <T> ?例如:

public interface IExample<out T>
{
    ...
}

对比

public interface IExample<T>
{
    ...
}

最佳答案

out泛型中的关键字用于表示接口(interface)中的类型 T 是协变的。参见 Covariance and contravariance了解详情。

经典的例子是IEnumerable<out T> .自 IEnumerable<out T>是协变的,您可以执行以下操作:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

如果这不是协变的,上面的第二行将失败,即使从逻辑上讲它应该工作,因为字符串派生自对象。之前variance in generic interfaces已添加到 C# 和 VB.NET(在带有 VS 2010 的 .NET 4 中),这是一个编译时错误。

.NET 4 之后,IEnumerable<T>被标记为协变,并成为 IEnumerable<out T> .自 IEnumerable<out T>仅使用其中的元素,从不添加/更改它们,将可枚举的字符串集合视为可枚举的对象集合是安全的,这意味着它是协变

这不适用于 IList<T> 这样的类型, 自 IList<T>有一个 Add方法。假设这将被允许:

IList<string> strings = new List<string>();
IList<object> objects = strings;  // NOTE: Fails at compile time

然后你可以调用:

objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object

这当然会失败 - 所以 IList<T>不能标记为协变。

顺便说一句,还有一个选项 in - 由比较接口(interface)之类的东西使用。 IComparer<in T> ,例如,以相反的方式工作。您可以使用具体的 IComparer<Foo>直接作为 IComparer<Bar>如果BarFoo 的子类,因为 IComparer<in T>接口(interface)是逆变

关于c# - 泛型中的 <out T> 与 <T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10956993/

相关文章:

r - 如何使用聚类协方差矩阵对回归系数进行线性假设检验?

c# - 这是实现线程安全读/写 Guid 属性的正确方法吗?

c# - c#中的属性返回是什么意思?

c# - 以编程方式为营销人员保存 Sitecore Web 表单

java - 如何在java中声明通用键值对数组

c# - 通用容器内是什么类型

numpy:计算互协方差,而不计算整个协方差矩阵

c# - 动态 LINQ 在 IQueryable 上聚合为单个查询

java - 从 Scala 调用 Java Generic Typed Method 会出现类型不匹配错误 : Scala

java - 为什么这个在 Java 7 中编译而不在 Java 8 中编译?