< out T> vs< T>在泛型中 [英] <out T> vs <T> in Generics
问题描述
< out T>
和< T>
之间有什么区别?例如:
public interface IExample< out T>
{
...
}
vs。
public interface IExample< T>
{
...
}
泛型中的 out
关键字用于表示接口中的类型T是协变的。有关详细信息,请参阅协变和逆变。
经典示例是 IEnumerable< out T>
。由于 IEnumerable< out T>
是协变的,因此您可以执行以下操作:
的IEnumerable<串GT; strings = new List< string>();
IEnumerable< object> objects = strings;
如果这不是协变的,上面的第二行将失败,即使逻辑上它应该工作,字符串派生自对象。在通用接口中出现差异之前,已将C#和VB.NET(in在.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; //注意:在编译时失败
然后您可以调用:
objects.Add(new Image()); //这应该起作用,因为IList< object>应该让我们添加任何**对象
这当然会失败 - 所以 IList< T>
不能被标记为covariant。
还有,btw是 in
- 这是比较接口之类的东西。例如, IComparer< in T>
的工作方式相反。如果 Bar,您可以直接使用
Foo
的子类,因为 IComparer<在T>
接口中是 contravariant 。
What is the difference between <out T>
and <T>
? For example:
public interface IExample<out T>
{
...
}
vs.
public interface IExample<T>
{
...
}
The out
keyword in generics is used to denote that the type T in the interface is covariant. See Covariance and contravariance for details.
The classic example is IEnumerable<out T>
. Since IEnumerable<out T>
is covariant, you're allowed to do the following:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
The second line above would fail if this wasn't covariant, even though logically it should work, since string derives from object. Before variance in generic interfaces was added to C# and VB.NET (in .NET 4 with VS 2010), this was a compile time error.
After .NET 4, IEnumerable<T>
was marked covariant, and became IEnumerable<out T>
. Since IEnumerable<out T>
only uses the elements within it, and never adds/changes them, it's safe for it to treat an enumerable collection of strings as an enumerable collection of objects, which means it's covariant.
This wouldn't work with a type like IList<T>
, since IList<T>
has an Add
method. Suppose this would be allowed:
IList<string> strings = new List<string>();
IList<object> objects = strings; // NOTE: Fails at compile time
You could then call:
objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
This would, of course, fail - so IList<T>
can't be marked covariant.
There is also, btw, an option for in
- which is used by things like comparison interfaces. IComparer<in T>
, for example, works the opposite way. You can use a concrete IComparer<Foo>
directly as an IComparer<Bar>
if Bar
is a subclass of Foo
, because the IComparer<in T>
interface is contravariant.
这篇关于< out T> vs< T>在泛型中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!