日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > C# > 正文

C#4.0新特性:協(xié)變與逆變中的編程思想

2023-05-20 20:23:34
字體:
供稿:網(wǎng)友

現(xiàn)在我們接著來談?wù)凜#4.0中一個重要的新特性:協(xié)變(Covariance)與逆變(Contravariance)。對于協(xié)變與逆變,大家肯定不會感到陌生,但是我相信有很多人不能很清晰地說出他們之間的區(qū)別。我希望通過這篇文章能夠讓讀者更加深刻的認識協(xié)變與逆變。但是也不排除另一種可能,那就是讀者這篇文章你對這兩個概念更加模糊。文章一些內(nèi)容僅代表個人觀點,如有不妥,還望指正。

1、兩個概念:強類型與弱類型

為了后面敘述方便,我現(xiàn)在這里自定義兩個概念:強類型和弱類型。在本篇文章中,強類型和弱類型指的是兩個具有直接或者間接繼承關(guān)系的兩個類。如果一個類是另一個類的直接或者間接基類,那么它為弱類型,直接或者間接子類為強類型。后續(xù)的介紹中會用到的兩個類Foo和Bar先定義在這里。Bar繼承自Foo。Foo是弱類型,而Bar則是強類型。

public class Foo { //Others Members... }

public class Bar:Foo { //Others Members... }

有了強類型和弱類型的概念,我們就可以這樣的定義協(xié)變和逆變:如果類型TBar是基于強類型Bar的類型(比如類型參數(shù)為Bar的泛型類型,或者是參數(shù)/返回值類型為Bar的委托),而類型TFoo是基于弱類型Foo的類型,協(xié)變就是將TBar類型的實例賦值給TFoo類型的變量,而逆變則是將TFoo類型的實例賦值給TBar類型的變量。

2、委托中的協(xié)變與逆變的使用

協(xié)變和逆變主要體現(xiàn)在兩個地方:接口和委托,先來看看在委托中如何使用協(xié)變和逆變。現(xiàn)在我們定義了如下一個表示無參函數(shù)的泛型委托Function,類型參數(shù)為函數(shù)返回值的類型。泛型參數(shù)之前添加了一個out關(guān)鍵字表示T是一個協(xié)變變體。那么在使用過程中,基于強類型的委托Fucntion實例就可以賦值給基于弱類型的委托Fucntion變量。

public delegate T Function<out T>();

class Program
         {
                   static void Main()
                   {
                            Function funcBar = new Function(GetInstance);
                            Function funcFoo = funcBar;
                            Foo foo = funcFoo();
                   }
                   static Bar GetInstance()
                   {
                            return new Bar();
                   }
          }

接下來介紹逆變委托的用法。下面定義了一個名稱為Operate的泛型委托,接受一個具有泛型參數(shù)類型的參數(shù)。在定義泛型參數(shù)前添加了in關(guān)鍵字,表示T是一個基于逆變的變體。由于使用了逆變,我們就可以將基于弱類型的委托Operate實例就可以賦值給基于強類型的委托Operate變量。

public delegate void Operate<in T>(T instance);

class Program
          {
                   static void Main()
                   {
                            Operate opFoo = new Operate(DoSth);
                            Operate opBar = opFoo;
                            opBar(new Bar());
                   }
                   static void DoSth(Foo foo)
                   { //Others... }
          }

 3、接口中的協(xié)變與逆變的使用

接下來我們同樣通過一個簡單的例子來說明在接口中如何使用協(xié)變和逆變。下面定義了一個繼承自 IEnumerable接口的IGroup集合類型,和上面一樣,泛型參數(shù)T之前的out關(guān)鍵字表明這是一個協(xié)變。既然是協(xié)變,我們就可以將一個基于強類型的委托IGroup實例就可以賦值給基于弱類型的委托IGroup變量。

public interface IGroup<out T> : IEnumerable
        { }
        public class Group : List, IGroup
         { }
         public delegate void Operate<in T>(T instance); 
        class Program 
        {
                 static void Main() 
                {
                         IGroup groupOfBar = new Group();
                         IGroup groupOfFoo = groupOfBar;
                         //Others...
                 }
         }

下面是一個逆變接口的例子。首先定義了一個IPaintable的接口,里面定義了一個可讀寫的Color屬性,便是實現(xiàn)該接口的類型的對象具有自己的顏色,并可以改變顏色。類型Car實現(xiàn)了該接口。接口IBrush定義了一把刷子,泛型類型需要實現(xiàn)IPaintable接口,in關(guān)鍵字表明這是一個逆變。方法Paint用于將指定的對象粉刷成相應(yīng)的顏色,表示被粉刷的對象的類型為泛型參數(shù)類型。Brush實現(xiàn)了該接口。由于IBrush定義成逆變,我們就可以將基于強類型的委托IBrush實例就可以賦值給基于弱類型的委托IBrush變量。

public interface IPaintable 
        {
                 Color Color
                 {
                         get;
                         set;
                 }
         }
         public class Car : IPaintable
         {
                 public Color Color { get; set; }
          }
         public interface IBrush<in T> where T : IPaintable
         {
                 void Paint(T objectToPaint, Color color);
         }
         public class Brush : IBrush where T : IPaintable 
        {
                 public void Paint(T objectToPaint, Color color)
                 {
                         objectToPaint.Color = color; 
                }
         }
         class Program 
        {
                 static void Main() 
                {
                         IBrush brush = new Brush();
                         IBrush carBrush = brush;
                         Car car = new Car(); 
                        carBrush.Paint(car, Color.Red);
                         Console.WriteLine(car.Color.Name); 
                }
         }

4、從Func看協(xié)變與逆變的本質(zhì)

接下來我們來談?wù)剠f(xié)變和逆變的本質(zhì)區(qū)別是什么。在這里我們以我們非常熟悉的一個委托Func作為例子,下面給出了該委托的定義。我們可以看到Func定義的兩個泛型參數(shù)分別屬于逆變和協(xié)變。具體來說輸入?yún)?shù)類型為逆變,返回值類型為協(xié)變。

public delegate TResult Func<in T, out TResult>(T arg);

再重申以下這句話“輸入?yún)?shù)類型為逆變,返回值類型為協(xié)變”。然后,你再想想為什么逆變用in關(guān)鍵字,而協(xié)變用out關(guān)鍵字。這兩個不是偶然,實際上我們可以將協(xié)變/逆變與輸出/輸入匹配起來。

我們再從另一個角度來理解協(xié)變與逆變。我們知道接口代表一種契約,當一個類型實現(xiàn)一個接口的時候就相當于簽署了這份契約,所以必須是實現(xiàn)接口中所有的成員。實際上類型繼承也屬于一種契約關(guān)系,基類定義契約,子類“簽署”該契約。對于類型系統(tǒng)來說,接口實現(xiàn)和類型繼承本質(zhì)上是一致的。契約是弱類型,簽署這份契約的是強類型。

將契約的觀點應(yīng)用在委托上面,委托實際上定義了一個方法的簽名(參數(shù)列表和返回值),那么參數(shù)和返回值的類型就是契約,現(xiàn)在的關(guān)鍵是誰去履行這份契約。所有參數(shù)是外界傳入的,所以基于參數(shù)的契約履行者來源于外部,也就是被賦值變量的類型,所以被賦值變量類型是強類型。而對于代理本身來說,參數(shù)是一種輸入,也就是一種采用in關(guān)鍵字表示的逆變。

而對于委托的返回值,這是給外部服務(wù)的,是委托自身對外界的一種承諾,所以它自己是契約的履行著,因此它自己應(yīng)該是強類型。相應(yīng)地,對于代理本身來說,返回值是一種輸出,也就是一種采用out關(guān)鍵字定義的協(xié)變。

也正式因為這個原因,對于一個委托,你不能將參數(shù)類型定義成成協(xié)變,也不能將返回類型定義成逆變。下面兩中變體定義方式都是不能通過編譯的。

delegate TResult Fucntion<out T, TResult>(T arg);

delegate TResult Fucntionin TResult>(T arg);

說到這里,我想有人要問一個問題,既然輸入表示逆變,輸出表示協(xié)變,委托的輸出參數(shù)應(yīng)該定義成協(xié)變了?非也,實際上輸出參數(shù)在這里既輸出輸出,也輸出輸入(畢竟調(diào)用的時候需要指定一個對應(yīng)類型的對象)。也正是為此,輸出參數(shù)的類型及不能定義成協(xié)變,也不能定義成逆變。所以下面兩種變體的定義也是不能通過編譯的。

delegate void Action<in T>(out T arg);

delegate void Action<out T>(out T arg);

雖然這里指介紹了關(guān)于委托的協(xié)變與逆變,上面提到的契約和輸入/輸出的關(guān)系也同樣適用于基于接口的協(xié)變與逆變。你自己可以采用這樣的方式去分析上面一部分我們定義的IGroup和IBrush。

5、逆變實現(xiàn)了“算法”的重用

實際上關(guān)系協(xié)變和逆變體現(xiàn)出來的編程思想,還有一種我比較推崇的說法,那就是:協(xié)變是繼承的體現(xiàn),而逆變體現(xiàn)的則是多態(tài)。實際上這與上面分析的契約關(guān)系本質(zhì)上是一致的。

關(guān)于逆變,在這里請容我再啰嗦一句:逆變背后蘊藏的編程思想體現(xiàn)出了對算法的重用——我們?yōu)榛惗x了一套操作,可以自動應(yīng)用于所有子類的對象。

上一篇:C#的前途如何

下一篇:C#,自然的進步

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
在线观看一区| 国产黄色片大全| 国产成人一二三区| 日韩一级视频在线观看| 欧美一级久久久久久久久大| 久久精品电影| 欧美日韩精品免费看| 免费在线观看国产黄| 亚洲欧洲日产国码av系列天堂| 丰满少妇一区二区| 九色蝌蚪视频在线| 日韩久久精品网| 欧美日韩综合色| 91精品999| 精品福利一区二区三区| 黄色一级大片在线免费看国产一| 国产丝袜一区二区| 最近中文av字幕在线中文 | 在线综合 亚洲 欧美中文字幕| wwwwww在线观看| 午夜福利一区二区三区| av免费观看国产| 亚洲高清视频在线| 精品一区二区三区中文字幕| 91精选在线| 精品视频999| 欧美中日韩在线| 韩日中文字幕第一页| 99国内精品| 欧美日韩亚洲第一| 亚洲第一视频| 97久久精品午夜一区二区| 中文字幕日韩第一页| 精品精品久久| 自拍日韩亚洲一区在线| 日韩视频一区| 快she精品国产999| 亚洲免费看av| 欧美一级日韩一级| 欧美日韩亚洲综合| 国内精品露脸在线视频播放| 91精品国产综合久久福利 | 亚洲福利精品视频| 亚洲一区在线观看免费| 国产调教精品| 国产高清一区| 精品在线91| 国产极品嫩模在线视频一区| 久久99精品久久久久久青青日本| 精品三级在线| 天堂中文在线视频| 日韩三级一区二区| 国产欧美日韩最新| 欧美日韩三级在线| 日韩wumaV| 精品国产免费视频| 在线中文字幕视频| 在线三级av| 久久久精品网| 欧美日韩国产高清| 日韩视频一区在线观看| 中文精品电影| 欧美日韩激情一区| 日韩中文字幕网| 亚洲成av人综合在线观看| 国产丝袜一区| 五月天久久比比资源色| 91精品国产综合久久久久| 伊人伊成久久人综合网小说| 欧美午夜精品在线| 国产日韩中文在线| 天堂在线中文资源| 一二三区精品视频| 精品999在线| 日韩视频免费直播| 人人做人人澡人人爽欧美| 极品久久久久久| 久久精品免费看| 久久精品国产视频| 国产h片在线观看| 91久久精品网| 中文字幕 亚洲一区| 婷婷综合福利| 视频一区三区| 一级网站免费观看| 精品视频在线视频| 中文字幕在线播出| 日韩一级精品| 中文字幕在线欧美| 精品综合久久久久| 国产高清精品在线观看| 日本精品在线播放| av亚洲免费| 日韩精品视频免费看| av免费在线播放| 亚洲校园欧美国产另类 | 欧美日韩综合在线免费观看| 中文字幕欧美日韩在线不卡| 高清日韩中文字幕| 中文字幕在线国产| 国产性一级片| 色综合婷婷久久| 欧美日韩性视频一区二区三区 | 国产高清在线一区| 国产在线观看精品| 国产一区不卡精品| 日韩欧美色综合| 国产一卡二卡3卡4卡四卡在线 | 国产小视频免费在线观看| 精品网站999| 不卡一二三区| 日韩国产专区| 国产精品一区二三区| 人成免费在线视频| 欧美日韩国产不卡在线看| 亚洲免费观看在线观看| 美女在线视频一区| 92久久精品| 国产黄色在线播放| 国产欧美日韩第一页| 97最新国自产拍视频在线完整在线看| 黄色片免费看| 日韩欧美在线综合| 日韩欧美国产三级| 日韩欧美亚洲区| 国产在线精品日韩| 国产一区精品| 日本精品在线播放| aaa欧美日韩| 日韩一级免费在线观看| 国产在线观看黄色| 国产xxx在线| 在线日韩精品视频| 在线精品日韩| 亚州黄色一级| 欧美日韩中文字幕日韩欧美| 欧美日韩国产黄色| 日韩福利视频导航| 国产不卡一区二区在线观看| 国产在线播放一区二区| 久久人人88| 日韩在线视频观看正片免费网站| 精品亚洲成a人片在线观看| 日韩精品在线网站| 在线免费播放av| 精品欧美日韩精品| a视频免费看| 一区二区欧美国产| 欧美中文字幕精品| 91精品国产自产在线丝袜啪| 中文精品电影| 国产黄色片中文字幕| 国产久卡久卡久卡久卡视频精品| 国产卡1卡2卡三卡在线| 国产香蕉精品视频| 日韩欧美中文字幕一区| 亚洲欧洲三级| 香蕉视频亚洲一级| 天天综合天天| 国产一区深夜福利| 97视频在线| 国产99在线 | 亚洲| 精品一二三四| 最新日韩中文字幕| 亚洲制服一区| 日韩中文首页| 日韩欧美字幕| 99综合精品久久| 欧美在线视频二区| 一区视频在线播放| 亚洲狠狠婷婷综合久久久久图片| 在线欧美日韩精品| 国产www在线观看| 日韩.com| 亚洲高清在线观看一区| 欧美一级免费在线观看| 精品视频—区二区三区免费| 日韩免费视频一区| 免费视频二区| 婷婷综合福利| 久久久99精品久久| 在线视频不卡一区二区| 日韩免费视频一区二区视频在线观看| 欧洲精品久久久| 国产日韩精品在线看| 天天综合天天| 中文字幕在线日韩| 91精品国产91久久久久久不卡 | 91av久久久| 中文国产字幕在线观看| 日韩精品福利一区二区三区| 日韩视频一区二区在线观看| 午夜伊人狠狠久久| 人成免费在线视频| 欧美日韩亚洲一区| 一区二区三区中文字幕在线观看| 亚洲欧美久久234| 欧美99久久| 不卡视频一区二区三区| 日本精品在线| 欧美中文字幕第一页| 樱花草www在线观看| 中文网丁香综合网| 精品久久在线观看| 中文精品电影| 欧美日韩成人综合| 日韩中文字幕久久| 精品播放一区二区| 91精品国产高清91久久久久久| 午夜少妇久久久久久久久| 91精品国产全国免费观看 | 欧美日韩国产一区| 91久久中文| 精品日本视频| 欧美高清一级片在线| 精品网站999| 日韩精品视频中文字幕| 日本国产一区| 日韩国产在线不卡视频| 一区在线免费| 亚洲娇小xxxx欧美娇小| 日韩欧美中文字幕在线观看| 欧美日韩亚洲系列| 一区二区欧美国产| 亚洲欧美中文在线视频| 91精品视频在线| 国产日韩精品在线看| 亚洲第一网中文字幕| 国产中文伊人| 国产一级在线免费观看| 久久久综合av| 欧美国产一级片| 免费网站看黄yyy222| 日韩一级中文字幕| 在线综合 亚洲 欧美中文字幕| 国产在线第一页| 精品熟女一区二区三区| 国产一卡二卡3卡4卡四卡在线| 日本中文字幕在线观看| 欧美在线日韩精品| 久久久精品午夜少妇| 国产成人精品网址| 国产欧美日韩视频| 欧美日韩精品三区| 欧美日韩亚洲视频| 欧美中文字幕在线观看视频| 91精品国产入口| 国产一区精品在线| av一级在线| www在线播放| 欧美天堂一区二区| 欧美三级日韩在线| 本道综合精品| 国产一区 二区 三区一级| 一级特黄大欧美久久久| 91精品在线视频观看| 在线资源av| 日韩在线视频观看| 在线日韩中文| 欧美久久综合性欧美| 亚洲男女av一区二区| 一二三区精品视频| www 日韩| 亚洲欧洲日韩在线| 最近中文字幕第一页| 精品日本视频| aa国产成人| 欧美日韩精品是欧美日韩精品| 国产视频aaa| 亚洲v中文字幕| 日韩精品视频在线看| 黄色在线播放网站| 国产福利在线导航| 日韩av一区二区在线观看| 在线看的av| 免费精品国产自产拍观看| 国产欧美日韩不卡免费| 免费视频国产一区| 精品久久蜜桃| 韩国av一区二区| 久久精品欧美日韩精品| 午夜国产福利在线观看| 国产一级片在线播放| 中文天堂资源在线| 老司机久久99久久精品播放免费| 欧美日韩国产一区中文午夜| 亚洲福利视频在线| 91精品国产综合久久精品| 日本免费看黄| 久久精品国产视频| 日本免费在线视频不卡一不卡二| 中文字幕日韩欧美在线视频| 中文精品视频| 欧美成人精品在线| 欧美日韩综合视频| 国产黄在线播放| 一本一道久久a久久精品综合蜜臀 一本一道综合狠狠老 | 亚洲大片精品永久免费| 91精品999| www.老鸭窝.com| 精品人妻一区二区三区视频| 91精品国产自产在线| 一区二区三区在线免费| 亚洲乱码中文字幕| 91精品国产入口| 欧美高清一级片在线| 91精品视频观看| 日韩精品中文在线观看| 美女在线视频一区| 免费精品国产自产拍观看| 中文字幕成人乱码在线电影| 亚洲免费婷婷| 中文字幕日韩视频| 中文字幕精品国产| 日韩午夜黄色| 日韩三级精品| 在线视频你懂得一区| 日韩三级视频在线播放| av一区在线观看| 亚洲永久字幕| 欧美日韩国产系列| 国产男女av| 欧美不卡视频| 欧美日韩中文精品| 顶级网黄在线播放| 中文欧美字幕免费| 91精选在线| 欧美亚洲另类制服自拍| 精品欧美不卡一区二区在线观看| 久久精品在线观看| 精品久久九九| 91 中文字幕| 亚洲国产欧美日韩精品| 亚洲欧洲国产视频| 欧美日韩精品在线观看| 九七久久人人| 日韩免费高清一区二区| 日韩欧美专区在线| 日韩网站中文字幕| 日韩国产亚洲欧美| 日韩视频 中文字幕| 中文字幕精品国产| 日韩精品国产欧美| 在线欧美一级视频| 国产 欧美 日韩 在线| 亚洲成av人片在线| 久久 天天综合| 日韩欧美资源站| 日韩欧美在线精品| 中文在线日韩| 青青国产91久久久久久| 不卡专区在线| 一区二区不卡久久精品| 午夜福利一区二区三区| 欧美日韩亚洲一| 国产视频不卡| 精品乱子伦一区二区| 欧美中文字幕视频在线观看| 亚洲第一视频| 精品999在线| 精品调教chinesegay| 国产一二三精品| 中文天堂在线一区| 亚洲乱码中文字幕| 国产拍揄自揄精品视频麻豆| 蜜桃久久av| 亚洲午夜久久| 精品中文字幕在线| 国产高清在线观看| wwwwww在线观看| 黄色在线播放网站| 国产一区三区三区| 中文天堂资源在线| 欧美日韩国产三级| 中文字幕成人乱码在线电影| 日韩精品视频在线看| 日韩欧美中文字幕精品| 日韩视频在线免费看| 中文字幕日韩高清| 中文字幕日韩欧美在线视频| aaa欧美日韩| 久久视频免费看| 日韩欧美综合视频| 在线手机中文字幕| 欧美高清一级片在线| 视频一区二区精品的福利| 日韩欧美在线视频| 欧美sm一区| av午夜在线| 国产乱一区二区| 欧美一级在线观看| 亚洲综合三区| 国产黄在线看| 日韩欧美专区在线| 97视频在线| 91精品久久久久久久久久入口| 亚洲日产av中文字幕| 国产一区日韩| 国产黄色小视频| 亚洲大片免费看|