C# 之协变与逆变

概述

写在前头,网上关于协变逆变的文章写写得真是让人一头雾水,微软官方文档更是重量级,仿佛不想让人懂。

按照官方解释:

  • 协变:能够使用比原始指定的派生类型的派生程度更大(更具体)的类型;
  • 逆变:能够使用比原始指定的派生类型的派生程度更新(更抽象)的类型;

为什么需要协变与逆变

假设有一个这样的场景:

Speak<Chinese> speak1 = new Speak<Chinese>();
Speak<Human> speak2 = speak1;

一般情况下,这样的直接指向是不可以的,编译器会报错;

这个时候就需要用到协变和逆变了;

认识协变与逆变

首先,使用协变与逆变有一个前提,就是只能用在接口或者委托上;

协变

协变需要在接口的泛型参数上加上out:

public interface ISpeak<out T>
{
    public T SpeakLanguage();
}

这里的out可以理解为出参,就是T在这个接口里只能作为返回值使用,或者作为只读属性的类型使用,不能作为方法的参数使用;

这个时候再执行:

Speak<Human> speak2 = speak1;

编译器就不会报错了;

因此可以总结协变的解释:如果存在一个泛型接口 Interface<T>,它的泛型参数子类类型 Interface<Chinese> 可以安全地转换为泛型父类类型 Interface<Human>,这个过程就称为协变;

逆变

协变需要在接口的泛型参数上加上in:

public interface ISpeak<in T>
{
    public void SpeakLanguage(T t);
}

逆变中T只能作为方法的入参的类型使用,不能作为返回值使用;

当使用逆变时,执行:

Speak<Human> speak1 = new Speak<Human>();
Speak<Chinese> speak2 = speak1;

编译器也不会报错;

所以逆变的解释为:如果存在一个泛型接口 Interface,它的泛型参数父类类型 Interface<Human> 可以安全地转换为泛型子类类型 Interface<Chinese>,这个过程就称为逆变;

要注意的是,并不是说逆变就是把父类的对象引用安全地指向子类的对象引用了,协变与逆变是不能抛开泛型谈的;假如我们不以泛型讨论这个问题,众所周知父类的对象引用是不能安全地指向子类对象引用的,相反,子类的对象引用是可以安全地指向父类的,也就是子类转换为父类是安全的;

深入了解协变与逆变

协变

假设有这样的一个场景:

public interface ISport<T>
{
    void Method1(T param);
    T Method2();
}

public class Sport<T> : ISport<T>
{
    public void Method1(T param)
    {
    }

    public T Method2() => default(T);
}

当我们尝试运行这样的代码:

ISport<Human> sport = new Sport<Chinese>();
var temp = sport.Method2();
sport.Method1();

对于 sport,它在调用 sport.Method2() 方法的时候,要求返回的是一个 Human 类型的对象,但在这个代码中,Method2() 方法是在 Sport<T> 中实现的,这里返回的是一个 Chinese类型;对于这种情况,是安全的,没有问题;

但是同样的道理。对于Method1() 来说就不安全了,当调用Method1() 的时候,按实现应该传入一个 Chinese 类型的对象,但因为是使用sport调用的,所以只能传入一个Human类型的对象,此时就不安全了,这就是为什么要用协变限制T只能为返回值;

逆变

和协变差不多,懒得写了orz;

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇