< out T> vs< T>在泛型中 [英] <out T> vs <T> in Generics

查看:122
本文介绍了< out T> vs< T>在泛型中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

< 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,您可以直接使用 IComparer< 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.

这篇关于&lt; out T&gt; vs&lt; T&gt;在泛型中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆