<out T>和<T>之间的区别是什么?例如:
<out T>
<T>
public interface IExample<out T> { ... }
vs。
public interface IExample<T> { ... }
从你发布的链接....
对于泛型类型参数, out关键字指定类型 参数为协变. .
对于泛型类型参数, out关键字指定类型 参数为协变.
更多信息请参见Covariance and contravance (c# and Visual Basic)。http://msdn.microsoft.com/en-us/library/ee207183.aspx
泛型中的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(在。NET 4和VS 2010中),这是一个编译时错误。
在。net 4之后,IEnumerable<T>被标记为协变,并成为IEnumerable<out T>。由于IEnumerable<out T>只使用其中的元素,而从不添加/更改它们,因此它将可枚举的字符串集合视为可枚举的对象集合是安全的,这意味着它是协变。
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>以相反的方式工作。如果Bar是Foo的子类,你可以直接使用具体的IComparer<Foo>作为IComparer<Bar>,因为IComparer<in T>接口是逆变。
in
IComparer<in T>
Bar
Foo
IComparer<Foo>
IComparer<Bar>
"out T"表示类型T是"协变"。这限制了T只能作为泛型类、接口或方法的方法中的返回(出站)值出现。其含义是,可以将类型/接口/方法转换为具有T超类型的等效类型 例如,ICovariant<out Dog>可以转换为ICovariant<Animal>
out T
T
ICovariant<out Dog>
ICovariant<Animal>
考虑,
class Fruit {} class Banana : Fruit {} interface ICovariantSkinned<out T> {} interface ISkinned<T> {}
函数,
void Peel(ISkinned<Fruit> skinned) { } void Peel(ICovariantSkinned<Fruit> skinned) { }
接受ICovariantSkinned<Fruit>的函数将能够接受ICovariantSkinned<Fruit>或ICovariantSkinned<Banana>,因为ICovariantSkinned<T>是协变接口,而Banana是Fruit的类型,
ICovariantSkinned<Fruit>
ICovariantSkinned<Banana>
ICovariantSkinned<T>
Banana
Fruit
接受ISkinned<Fruit>的函数将只能接受ISkinned<Fruit>。
ISkinned<Fruit>
为了方便地记住in和out关键字的用法(以及协方差和逆变),我们可以将继承映像为包装:
String : Object Bar : Foo
我认为VS2022的这张截图是非常描述性的——它说明了这对泛型施加了什么样的约束:
我发现最简单的解释是在这个文章声明为
interface ISomeName<in T> < -表示T只能作为a传递 方法的参数(它进入接口的方法,就这样 在里面,也许这就是为什么我们使用here关键字“in” 只是巧合吗?) interface ISomeName<out T> < -表示T只能返回为 方法结果(它是我们从方法中接收到的结果,因此它会输出 它-哇,再次听起来是合法的!)
interface ISomeName<in T> < -表示T只能作为a传递 方法的参数(它进入接口的方法,就这样 在里面,也许这就是为什么我们使用here关键字“in” 只是巧合吗?)
ISomeName<in T>
interface ISomeName<out T> < -表示T只能返回为 方法结果(它是我们从方法中接收到的结果,因此它会输出 它-哇,再次听起来是合法的!)
ISomeName<out T>