繁体   English   中英

c# 协变通用参数

[英]c# covariant generic parameter

我试图理解这一点,但我没有从搜索中得到任何适当的结果。

在 c# 4 中,我可以做到

    public interface IFoo<out T>
    {

    }

这与

    public interface IFoo<T>
    {

    }

我所知道的是out使泛型参数协变(??)。 有人可以举例说明<out T>部分的用法吗? 还有为什么只适用于接口和委托而不适用于类?

对不起,如果它是重复的,如果是,请关闭它。

有人可以举例说明 out T 部分的用法吗?

当然。 IEnumerable<T>是协变的。 这意味着你可以这样做:

static void FeedAll(IEnumerable<Animal> animals) 
{
    foreach(Animal animal in animals) animal.Feed();
}

...

 IEnumerable<Giraffe> giraffes = GetABunchOfGiraffes();
 FeedAll(giraffes);

“协变”是指在泛型类型中保留了类型实参的赋值兼容关系 GiraffeAnimal的赋值兼容,因此该关系保留在构造类型中: IEnumerable<Giraffe>IEnumerable<Animal>的赋值兼容。

为什么只适用于接口和委托而不适用于类?

类的问题是类往往具有可变字段。 让我们举个例子。 假设我们允许这样做:

class C<out T>
{
    private T t;

OK,现在这个问题在你go之前仔细想清楚。 C<T>可以在构造函数之外有任何方法将字段t设置为默认值以外的值吗?

因为它必须是类型安全的,所以C<T>现在不能有将 T 作为参数的方法; T 只能退货。 那么谁设置 t,他们从哪里获得设置它的值

只有当 class 是不可变的时,协变 class 类型才真正起作用。 而且我们没有在 C# 中创建不可变类的好方法。

我希望我们这样做,但我们必须接受我们提供的 CLR 类型系统。 我希望将来我们可以更好地支持不可变类和协变类。

如果您对此功能感兴趣,请考虑阅读我关于我们如何设计和实现该功能的长系列。 从底部开始:

https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/

如果我们谈论的是通用方差:

协方差是关于从操作返回给调用者的值。

逆变它是相反的,它是关于调用者传递的值:

据我所知,如果类型参数仅用于 output,则可以使用 out。 但是,如果该类型仅用于输入,则可以使用 in。这很方便,因为编译器无法确定您是否可以记住哪种形式称为协变,哪种形式称为逆变。 如果在声明类型后不显式声明它们,则相关的转换类型是隐式可用的。

类中没有方差(协方差或逆变),因为即使您有一个仅将类型参数用于输入(或仅将其用于输出)的 class,您也无法指定 in 或 out 修饰符。 只有接口和委托可以有变体类型参数。 首先,CLR 不允许这样做。 从概念的角度来看,接口代表了一种从特定角度看待 object 的方式,而类是更实际的实现类型。

这意味着如果你有这个:

class Parent { } 
class Child : Parent { }

那么IFoo<Child>的实例也是IFoo<Parent>的一个实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM