c#筆記1-抗變與協變

來源:互聯網
上載者:User

標籤:

前言

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

  平時偶爾會遇到一些小問題,很多時候都是查了記住,或者簡單寫寫筆記,當時理解就過了,沒有形成文檔,等過段時間又遇到同樣的問題,又要重新去查去理解,甚是麻煩。希望以後把這些東西寫成文章,儘管可能是很小的問題,也當做筆記記錄。關於c#的一些概念、文法或者規範,就記錄在【c#筆記】。由於不是初學邊學邊記,所以沒有一定的時間和學習順序,只是平時遇到覺得有必要,就記錄下來。

一、遇到問題

  工作是基於.net3.5開發,實際過程遇到一個問題。假設我們有一個 Base 類,一個 Derived 類,Derived 繼承了 Base。如下:

    class Base    {    }    class Derived : Base    {    }  

  當我用IEnumerable<Base> 作為形參,List<Derived> 作為實參時,發現編譯出錯了!原本父類作為形參,傳遞子類是再正常不過的,但在泛型中確編譯不通過。

二、探究問題

  通常我們在設計參數和傳回值都有一個原則,參數要儘可能“泛”,傳回值要儘可能的“細”。泛,指得是用介面或者父類作為參數,這樣可以接收更多的參數類型;細,指的是返回具體類型,這樣可以更好說明方法的作用。

  舉個例子:

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

  可見,參數的“泛”可以提供更大的靈活性。

  接著就進入本次的主題:抗變與協變。需要說明的是,抗變與協變是在4.0開始支援的。假設有一個方法需要Derived集合作為參數,那麼基於上面的原則,我們會這樣設計:

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

  接著我們向下面這樣調用,在3.5下就會發現編譯不通過,提示無法將 List<Derived>轉換為IEnumerable<Base>。

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

  同樣的代碼,我們拿到4.0下,發現編譯通過了。比較 IEnumerable泛型介面,我們發現4.0下的定義為:  

 public interface IEnumerable<out T> : IEnumerable

  發現多了 out 關鍵字,這就是協變。msdn對於型別參數的解釋是:out T 要枚舉的對象的類型。該型別參數是協變的。即可以使用指定的類型或派生程度更高的類型。

  我們可以這樣理解協變,參數的類型就是協變的,父類用子類代替,也就是子類當父類使用。

  理解協變後,抗變就好理解了。函數的傳回值就是抗變的,子類用父類代替,也就是父類當子類使用。在非泛型的情況下,我們可以這樣接收方法的傳回值:  

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

  當然,我們覺得這樣調用也應該是可以的:  

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

  在3.5下,這樣同樣會編譯錯誤。4.0下就沒有問題。

三、總結

   協變與抗變的概念其實我們經常遇到(參數協變、傳回值抗變),而且我們也會習慣的這樣設計。但對於泛型,.net 到了4.0才提供這樣的支援,這為泛型的使用提供了更大的靈活性。

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

c#筆記1-抗變與協變

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.