.NET中的逆变协变

  MSDN上的说法:

  协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型----------(注意,这里说的可以使用更具体的类型是指可以给跟具体的类型传递相对不太具体的参数)。 泛型类型参数支持协变和逆变,可在分配和使用泛型类型方面提供更大的灵活性。 在引用类型系统时,协变、逆变和不变性具有如下定义。 这些示例假定一个名为 Base 的基类和一个名为 Derived 的派生类。使你能够使用比原始指定的类型更泛型(派生程度更小)的类型。你可以向 IEnumerable<Derived> 类型的变量分配 IEnumerable<Base>(在 Visual Basic 中为 IEnumerable(Of Base))的实例。

  感觉MSDN说的还是有些拗口。  

  逆变:Contravariance,类型参数用 in 关键字。

  简单来说就是假设有一个泛型逆变接口IDo<in T>,有两个可以替换T的类型A和B时,B如果继承自A时,可以将IDo<A>的实例赋值给IDo<B>,例如:

  

private void button1_Click(object sender, EventArgs e)
{

  IDo<A> a = new DoT<A>();
  IDo<B> b = new DoT<B>();

  Run run = new Run();
  run.Set<D>(a);
}

 

interface IDo<in T> {   void Do(T t); } class A { } class B : A { } class D : B { } class C : A { } class E : C { } class DoT<T> : IDo<T> {   public void Do(T t)   {     MessageBox.Show(t.GetType().ToString());   } } class Run {   public void Set<T>(IDo<T> it) where T : new()   {     it.Do(new T());//返回D的类型     MessageBox.Show(it.GetType().ToString());//返回A的接口类型   } }

  协变:Covariance,类型使用out关键字。

  这个相对于逆变来说更容易理解,当有接口IDo<out T>时,有两个可以替换T的类型A和B时,B如果继承自A时,可以将IDo<B>的实例赋值给IDo<A>,说这更容易理解是因为里氏替换大家会熟悉些,这个看起来有些像,不过不要混淆,这是两回事,例子:

    interface IDo<out T>
    {
        T get();
    }    

    private void button1_Click(object sender, EventArgs e)
    {
        IDo<A> a = new DoT<A>(); IDo<B> b = new DoT<B>(); Run run = new Run(); run.Set<A>(b); }

  另外需要注意的,使用了in的T只能用做输入参数,不能用做返回值。使用了out做参数的只能用做返回值,不能做输入参数。

  我曾经写过一个随笔,实现中使用了协变的特性:由继承演变为角色扮演

转载于:https://www.cnblogs.com/saaav/p/4197072.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值