日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

圖文詳解C#中的協變與逆變_C#教程

作者:阿輝 ? 更新時間: 2022-04-11 編程語言

前言

這篇文章簡單說說C#中的協變和逆變。

在C#編程中,由于存在類型之間的強制轉換,很容易會出現所謂的類型可變性說法,存在協變、逆變、不變三種。

就比如前一篇文章介紹的泛型概念,如果創建了泛型類型的實例,編譯器會接受泛型類型聲明以及類型參數來創建構造類型。但是在日常使用過程中,我們可能會將派生類型分配給基類型的變量,有時候會出現錯誤。

這里就存在一個賦值兼容性問題。

每一個變量都有一種類型,可以將派生類對象的實例賦值給基類變量(好比之前子類聲明的變量可以賦值給父類聲明的變量一樣)。

如下所示:

        class People
        {
            public int Age = 27;
        }
 
        class AhuiPeople : People
        {
 
        }

?

            People ahui = new People();
            People people = new AhuiPeople();
 
            Console.WriteLine("Age:"+people.Age);
            Console.ReadKey();

協變和逆變

我們按照同樣的邏輯,在泛型委托中進行這種強類型的轉換,會發現即使基類和派生類之間可以進行正常的轉換,但是委托之間不能進行轉換會出現異常錯誤提示。

具體如下代碼所示:

        delegate T AgeDelegate<T>();         
 
        static AhuiPeople GetAge()
        {
            return new AhuiPeople();
        }

在轉換過程中,委托的具體用法,但是這樣子編譯器提示錯誤。

            AgeDelegate<AhuiPeople> ahui = GetAge;
            AgeDelegate<People> people = ahui;

錯誤提示

這就是上面解釋的那樣子,基類和派生類之間可以進行轉換但是委托之間未存在關聯,無法進行強制類型的轉換。
那么想解決這個問題就引入了協變來解決。

如果派生類只是用于輸出值,那么這種結構化的委托有效性之間的常數關系叫做協變,可通過主動告知編譯器我們的期望,使用Out關鍵字標記委托聲明中的類型參數。

        delegate T AgeDelegate<out T>();   

修改成這樣子后,上面錯誤演示的代碼編譯器就可以正常編譯通過了。

上面簡單介紹了協變,那么接下來我們來看逆變是什么。

其實逆變就是在委托中既要聲明委托類型,也要在委托方法中有實參。

這種在期望傳入基類時允許傳入派生對象的特性叫做逆變。 逆變使用關鍵字in來標記。

具體如下代碼所示:

        delegate void AgeDelegate<in T>(T p); 
        static void GetAge(People p)
        {
            Console.WriteLine(p.Age);
        }
            AgeDelegate<People> ahui = GetAge;
            AgeDelegate<AhuiPeople> people = ahui;
 
            people(new AhuiPeople());
            Console.WriteLine();
            Console.ReadKey();

輸出結果

既然協變和逆變可以使用在委托上,那么接口上也可以使用,此時也需要使用out和in關鍵字。

總結

原文鏈接:https://www.cnblogs.com/netxiaohui/p/15865060.html

欄目分類
最近更新