<out T>和 和有什么不一样<T>?例如:
<out T>
<T>
public interface IExample<out T> { ... }
对比
public interface IExample<T> { ... }
泛型中的out关键字用于表示接口中的类型 T 是协变的。有关详细信息,请参阅协变和逆变。
out
经典的例子是IEnumerable<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 。
IEnumerable<T>
这不适用于类似 的类型IList<T>,因为IList<T>有一个Add方法。假设这是允许的:
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>接口是 逆变 的。
in
IComparer<in T>
IComparer<Foo>
IComparer<Bar>
Bar
Foo