国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

抗變與協(xié)變

2019-11-14 14:01:41
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

  工作一年了,平時(shí)也喜歡看看書(shū),逛逛園子;但說(shuō)到寫(xiě)博,還真的沒(méi)有,說(shuō)到底,只有一個(gè)字:懶!現(xiàn)在想改掉這個(gè)“毛病”了,希望多把平時(shí)工作學(xué)習(xí)到的知識(shí)和遇到的問(wèn)題記錄下來(lái),一是可以梳理自己的思路,加深理解;二是可以向更多的朋友學(xué)習(xí)和分享;三是可以鍛煉自己的寫(xiě)作水平;可謂百利而無(wú)一害!

  平時(shí)偶爾會(huì)遇到一些小問(wèn)題,很多時(shí)候都是查了記住,或者簡(jiǎn)單寫(xiě)寫(xiě)筆記,當(dāng)時(shí)理解就過(guò)了,沒(méi)有形成文檔,等過(guò)段時(shí)間又遇到同樣的問(wèn)題,又要重新去查去理解,甚是麻煩。希望以后把這些東西寫(xiě)成文章,盡管可能是很小的問(wèn)題,也當(dāng)做筆記記錄。關(guān)于c#的一些概念、語(yǔ)法或者規(guī)范,就記錄在【c#筆記】。由于不是初學(xué)邊學(xué)邊記,所以沒(méi)有一定的時(shí)間和學(xué)習(xí)順序,只是平時(shí)遇到覺(jué)得有必要,就記錄下來(lái)。

一、遇到問(wèn)題

  工作是基于.net3.5開(kāi)發(fā),實(shí)際過(guò)程遇到一個(gè)問(wèn)題。假設(shè)我們有一個(gè) Base 類(lèi),一個(gè) Derived 類(lèi),Derived 繼承了 Base。如下:

    class Base    {    }    class Derived : Base    {    }  

  當(dāng)我用IEnumerable<Base> 作為形參,List<Derived> 作為實(shí)參時(shí),發(fā)現(xiàn)編譯出錯(cuò)了!原本父類(lèi)作為形參,傳遞子類(lèi)是再正常不過(guò)的,但在泛型中確編譯不通過(guò)。

二、探究問(wèn)題

  通常我們?cè)谠O(shè)計(jì)參數(shù)和返回值都有一個(gè)原則,參數(shù)要盡可能“泛”,返回值要盡可能的“細(xì)”。泛,指得是用接口或者父類(lèi)作為參數(shù),這樣可以接收更多的參數(shù)類(lèi)型;細(xì),指的是返回具體類(lèi)型,這樣可以更好說(shuō)明方法的作用。

  舉個(gè)例子:

        string[] strs = new string[] { "hello", "Word" };        //這樣的缺點(diǎn)是數(shù)組就傳遞不了了,還要調(diào)用一次 ToList()        static void Test_1(List<string> list)        {        }        //正確的做法,應(yīng)該用IEnumerable<T>        static void Test_2(IEnumerable<string> list)        {        }  

  可見(jiàn),參數(shù)的“泛”可以提供更大的靈活性。

  接著就進(jìn)入本次的主題:抗變與協(xié)變。需要說(shuō)明的是,抗變與協(xié)變是在4.0開(kāi)始支持的。假設(shè)有一個(gè)方法需要Derived集合作為參數(shù),那么基于上面的原則,我們會(huì)這樣設(shè)計(jì):

  static void TestIn(IEnumerable<Base> bases)  {  }

  接著我們向下面這樣調(diào)用,在3.5下就會(huì)發(fā)現(xiàn)編譯不通過(guò),提示無(wú)法將 List<Derived>轉(zhuǎn)換為IEnumerable<Base>。

 List<Derived> listIn = new List<Derived>(); TestIn(listIn);

  同樣的代碼,我們拿到4.0下,發(fā)現(xiàn)編譯通過(guò)了。比較 IEnumerable泛型接口,我們發(fā)現(xiàn)4.0下的定義為:  

 public interface IEnumerable<out T> : IEnumerable

  發(fā)現(xiàn)多了 out 關(guān)鍵字,這就是協(xié)變。msdn對(duì)于類(lèi)型參數(shù)的解釋是:out 要枚舉的對(duì)象的類(lèi)型。該類(lèi)型參數(shù)是協(xié)變的。即可以使用指定的類(lèi)型或派生程度更高的類(lèi)型。

  我們可以這樣理解協(xié)變,參數(shù)的類(lèi)型就是協(xié)變的,父類(lèi)用子類(lèi)代替,也就是子類(lèi)當(dāng)父類(lèi)使用。

  理解協(xié)變后,抗變就好理解了。函數(shù)的返回值就是抗變的,子類(lèi)用父類(lèi)代替,也就是父類(lèi)當(dāng)子類(lèi)使用。在非泛型的情況下,我們可以這樣接收方法的返回值:  

  object obj = Test_3();  static string Test_3()  {    return "hello world";  }  

  當(dāng)然,我們覺(jué)得這樣調(diào)用也應(yīng)該是可以的:  

  IEnumerable<Base> listOut = TestOut();  static IEnumerable<Derived> TestOut()  {    return new List<Derived>();  }

  在3.5下,這樣同樣會(huì)編譯錯(cuò)誤。4.0下就沒(méi)有問(wèn)題。

三、總結(jié)

   協(xié)變與抗變的概念其實(shí)我們經(jīng)常遇到(參數(shù)協(xié)變、返回值抗變),而且我們也會(huì)習(xí)慣的這樣設(shè)計(jì)。但對(duì)于泛型,.net 到了4.0才提供這樣的支持,這為泛型的使用提供了更大的靈活性。

  ok,實(shí)際我們不怎么需要去理解概念性的東西,知道原理和理解怎么使用即可。以上是我的個(gè)人理解,如果有朋友想要更深入的理解,可以參見(jiàn)msdn。


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 武邑县| 萍乡市| 高台县| 甘泉县| 珠海市| 英吉沙县| 徐州市| 府谷县| 凉城县| 高唐县| 屏边| 朝阳市| 安福县| 钟祥市| 于都县| 尉氏县| 阿拉善盟| 远安县| 家居| 东兴市| 大庆市| 岑巩县| 淮滨县| 古交市| 土默特右旗| 沙河市| 富裕县| 中方县| 临洮县| 乌兰察布市| 安远县| 饶平县| 连云港市| 横山县| 库尔勒市| 中西区| 鹤壁市| 侯马市| 南漳县| 若羌县| 满洲里市|