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