C# <;out T>;vs<;T>;仿制药

C# <;out T>;vs<;T>;仿制药,c#,generics,covariance,C#,Generics,Covariance,和之间有什么区别?例如: public interface IExample<out T> { ... } 公共接口示例 { ... } vs 公共接口示例 { ... } 来自您发布的链接 对于泛型类型参数,out关键字指定 参数是协变的 编辑: 再次,从你发布的链接 有关详细信息,请参见协方差和逆变换(C#和Visual Basic) 泛型中的out关键字用于表示接口中的类型T是协变的。有关详细信息,请参阅 经典的例子是IEnumerable。由于IEnumerabl

之间有什么区别?例如:

public interface IExample<out T>
{
    ...
}
公共接口示例
{
...
}
vs

公共接口示例
{
...
}

来自您发布的链接

对于泛型类型参数,out关键字指定 参数是协变的

编辑: 再次,从你发布的链接

有关详细信息,请参见协方差和逆变换(C#和Visual Basic)


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

经典的例子是
IEnumerable
。由于
IEnumerable
是协变的,因此允许您执行以下操作:

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
然后你可以打电话:

objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object
对象。添加(新图像());//这应该是可行的,因为IList应该允许我们添加**任何**对象
这当然会失败,因此不能将IList标记为协变

顺便说一句,在中还有一个
选项,用于比较接口等<例如,code>IComparer
,其工作方式正好相反。如果
Bar
Foo
的子类,则可以直接使用具体的
IComparer
作为
IComparer
,因为
IComparer
接口是反变的。

out T
”表示类型
T
是“协变的”。它限制
T
在泛型类、接口或方法的方法中仅作为返回(出站)值出现。这意味着您可以将类型/接口/方法强制转换为具有超类型
T

例如,
ICovariant
可以强制转换为
ICovariant

考虑

class Fruit {}

class Banana : Fruit {}

interface ICovariantSkinned<out T> {}

interface ISkinned<T> {}
类水果{}
香蕉类:水果{}
接口IcoVariantSkined{}
接口被激活{}
以及功能,

void Peel(ISkinned<Fruit> skinned) { }

void Peel(ICovariantSkinned<Fruit> skinned) { }
void Peel(剥皮){
空皮(ICovariantSkinned skined){}
接受
ICovariantSkinned
的函数将能够接受
ICovariantSkinned
ICovariantSkinned
,因为
ICovariantSkinned
是协变接口,
Banana
水果的一种类型


接受
ISkinned
的函数将只能接受
ISkinned

为方便记忆
in
out
关键字的用法(以及协方差和逆变),我们可以将继承想象为包装:

String : Object
Bar : Foo

@ColeJohnson,因为
Image
是一个抽象类;)您可以执行
newlist(){Image.FromFile(“test.jpg”)}没有问题,或者您可以执行
新建列表(){new Bitmap(“test.jpg”)}也是。你的问题是
newimage()
是不允许的(你也不能做
var img=newimage();
通用
IList
就是一个奇怪的例子,如果你想要
object
s,你就不需要泛型了。@ReedCopsey你在评论中没有反驳你自己的答案吗?我不知道
out
强制执行只能返回
t
,直到我读到这个答案。整个概念现在更有意义了!好的例子是IObservable和IObserver,它们在mscorlib的系统ns中定义。公共接口IObservable和公共接口IObserver。同样,IEnumerator,IEnumerablet我遇到的最好的解释:。(这不是错误的方法吗?逆变=in=允许使用较少的派生类型来代替较多的派生类型。/convariance=out=允许使用较多的派生类型来代替较少的派生类型。就我个人而言,查看您的图表,我将其理解为与that.co u变量相反的(:对我而言)
void Peel(ISkinned<Fruit> skinned) { }

void Peel(ICovariantSkinned<Fruit> skinned) { }
String : Object
Bar : Foo