<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          五分鐘看完,徹底理解協(xié)變逆變

          共 2705字,需瀏覽 6分鐘

           ·

          2024-03-26 04:30

          前言

          其實(shí)這是c#的老知識點(diǎn)了,但是發(fā)現(xiàn)同事對這個(gè)竟然還一知半解,就和他們講解了下,順便也回顧了下,同事我也把我對這個(gè)的全部理解,融化成幾分鐘的講解,保證大家5分鐘內(nèi)全部理解,看不懂來打我。

          協(xié)變、逆變 解決的問題

          泛型類型轉(zhuǎn)換

          比如Person類是Student的父類,我們平時(shí)可以直接:

                Person A = new Student();
              

          這是所謂的隱式轉(zhuǎn)換,相信百分之999.99%的人都知道。

          然后隨著大家寫代碼越來越多,就會(huì)遇到這樣的場景。

                //我有一個(gè)集合
          //我手上有一批學(xué)生
          IEnumerable<Student> students = new List<Student>();
          //我要他們先做人
          IEnumerable<Person> peoples = students;

          第一次看到這種代碼,其實(shí)哪怕你一點(diǎn)不知道協(xié)變,逆變,你也覺得這是一段正常不過的代碼,因?yàn)槊總€(gè)學(xué)生都是人,都可以直接轉(zhuǎn)成 這個(gè)類型,那我一批學(xué)生不就是一批人嗎。

          是的,你這樣想絕對沒錯(cuò),不然微軟怎么會(huì)能讓你這樣寫沒問題還編譯通過呢?

          但是如果我自己寫一個(gè):

                //定義一個(gè)工作的泛型接口
          public interface IWork<T
          {
                      
          }

          實(shí)現(xiàn)類
          public class Work<T> : IWork<T
          {
                      
          }

          //直接報(bào)錯(cuò)
          IWork<Person> work = new Work<Student>();

          現(xiàn)實(shí)給了我們當(dāng)頭一棒,這時(shí)候,我們應(yīng)該找到 IEnumerable,選中然后狠狠的F12去看一下,為什么官方的就可以。

          2d3f2dba5043a781dcad630acc62d27e.webp

          我們發(fā)現(xiàn)官方在泛型前面多了一個(gè)out關(guān)鍵字。破案了~

          現(xiàn)在我們在我們的代碼中也加入out關(guān)鍵字

                public interface IWork<out T
          {
                      
          }

          public class Work<T> : IWork<T
          {
                      
          }
          IWork<Person> work = new Work<Student>();

          OK~代碼正常運(yùn)行。

          原則核心

          這里開始我們挑戰(zhàn)五分鐘速通,如果按照正常博客上來先講概念,別說五分鐘了,可能大家也就迷迷糊糊地看完了,所以我們直接整活。

          核心依據(jù)

          正如數(shù)學(xué)的發(fā)展是從1+1=2作為開始,我們也需要一些真理來支撐我們講下去。那么我們的核心依據(jù)就是:里氏替換——C#里,子類轉(zhuǎn)父類可以直接隱式轉(zhuǎn)換

          就這么短,就完事了?對,記住就行!!!

          Out/In 輸入輸出?

          講到這里,我們繼續(xù)忽悠,out是啥?來個(gè)翻譯!不就是輸出嗎?in是啥,不就是輸入嗎?那么帶入一下,Out不就是返回值嗎,In不就是入?yún)帷D遣痪褪欠椒ǖ奶卣髅础#ㄏ燃僭O(shè),再假設(shè))

          In:那么根據(jù)核心依據(jù),子類轉(zhuǎn)父類可以直接轉(zhuǎn),入?yún)⑷绻薅ㄊ荘erson類型,那么你給我限定為Student或者任意的Person類型的派生類,我都是可以接受的,因?yàn)槎际前踩模梢灾苯愚D(zhuǎn)換過來的。

          這種從基類轉(zhuǎn)向派生類的兼容,就是所謂的逆變。說白了,我讓你給我一個(gè)人,你說不行,我給你找個(gè)學(xué)生,那肯定是滿足需求的。

          Out:Out代表的是返回值,根據(jù)核心依據(jù),我返回的是Student類型,你說不行,你給我返回Person類型,那我不是笑開花了,我連Student都能返回,你讓我返回父類,那我不是直接轉(zhuǎn)就過去了,總歸是類型安全的。

          這種從派生類轉(zhuǎn)向基類的兼容,就是所謂的協(xié)變。

          說白了,我可以造個(gè)學(xué)生,結(jié)果你說給個(gè)人就行, 那不是so easy。

          In示意圖

          72bf81ad53afc99389f1d2ee0ca51388.webp

          Out示意圖

          8fc414f5657b244384fe67d6ebc8f98d.webp

          證明

          好了,我們說了這么多,至少證明下In/Out是代表的入?yún)⒑头祷刂蛋桑恐苯觭how you code: 當(dāng)Out作為返回值時(shí)的泛型沒有問題,但是入?yún)⒕蛨?bào)錯(cuò)了

          ad32c629ccac7c2f09d206517df2c27b.webp

          當(dāng)In作為入?yún)r(shí)的泛型沒有問題,但是返回值就報(bào)錯(cuò)了

          c3815c4457ff683ea3e35dcc00366e42.webp

          好了,這還需要再解釋嗎?最后我們總結(jié)下,逆變和協(xié)變就是讓方法有了泛型類型上的轉(zhuǎn)換能力,強(qiáng)化了方法的多態(tài)能力。

          問題點(diǎn)

          1、屬性為啥可以用逆變協(xié)變?

          屬性不就是get/set方法。

          2、為什么接口和委托可以用逆變協(xié)變,類不行?

          拜托你找一下共同點(diǎn),接口和委托的共同點(diǎn),都是行為,也就是方法為核心。接口里不能有字段。這也印證了我說的逆變協(xié)變最終是為方法服務(wù)的。

          之所以類不行,我大概理解是方法和實(shí)例是分開的,本身不和實(shí)例存儲(chǔ)在一起,也不是每個(gè)實(shí)例一份,如果逆變和協(xié)變可以服務(wù)類,那么會(huì)出現(xiàn)同樣的類型,但是每個(gè)實(shí)例內(nèi)部的同一個(gè)字段的類型都不一樣,這對于存儲(chǔ)和類型安全都是問題。

          3、逆變和協(xié)變有啥用?

          你...設(shè)計(jì)問題,我就有遇到,有時(shí)候用上能更加優(yōu)雅或者靈活的寫代碼吧,看你吧,少年。

          轉(zhuǎn)自:BruceNeter

          鏈接:cnblogs.com/qwqwQAQ/p/17622254.html

          瀏覽 43
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  aa大香蕉aa | 丁香五月天在线婷婷 | 欧美精品综合 | 国产免费靠逼视频 | 天堂网在线最新版www中文网 |