小编典典

对比在泛型

all

<out T>和 和有什么不一样<T>?例如:

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

对比

public interface IExample<T>
{
    ...
}

阅读 69

收藏
2022-05-29

共1个答案

小编典典

泛型中的out关键字用于表示接口中的类型 T 是协变的。有关详细信息,请参阅协变和逆变

经典的例子是IEnumerable<out T>。由于IEnumerable<out T>是协变的,因此您可以执行以下操作:

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

如果这不是协变的,那么上面的第二行将失败,即使在逻辑上它应该工作,因为 string 派生自
object。在将泛型接口的差异添加到 C#
和 VB.NET(在带有 VS 2010 的 .NET 4 中)之前,这是一个编译时错误。

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

这不适用于类似 的类型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- 用于比较接口之类的东西。 IComparer<in T>,例如,以相反的方式工作。您可以直接使用具体IComparer<Foo>作为IComparer<Bar>ifBar的子类Foo,因为IComparer<in T>接口是 逆变 的。

2022-05-29