亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

c#中的泛型

2019-11-14 13:29:36
字體:
來源:轉載
供稿:網友

      這篇文章主要來講講c#中的泛型,因為泛型在c#中有很重要的位置,對于寫出高可讀性,高性能的代碼有著關鍵的作用。當我多次看到自己團隊的代碼中包含著大量的非泛型集合,隱式的裝箱和拆箱操作時,我都會建議他們補一補泛型基礎。

     1,什么是泛型

    • 泛型是c#2中非常重要的一個新特性,它增強了代碼的可讀性,將大量的安全檢查從執行期轉移到編譯期,從而提高代碼的安全性和性能。從根本上來說,泛型實現了類型和方法的參數化。

     2,為什么要使用泛型,泛型解決了什么問題

我們先來看看下面的代碼(代碼只是為了演示泛型,沒有實際的意義),看看有什么問題?   

 1 class PRogram 2     { 3         static void Main(string[] args) 4         { 5             ArrayList array = new ArrayList(); 6             array.Add(1); 7             array.Add(2); 8             array.Add(3); 9             ArrayList resultArray = NumberSqrt(array);10             foreach (var item in resultArray)11             {12                 Console.WriteLine(item);13             }14         }15         public static ArrayList NumberSqrt(ArrayList array)16         {17             ArrayList sqrtArray = new ArrayList();18             foreach (var item in array)19             {20                 sqrtArray.Add(Math.Sqrt((double)(int)item));21             }22             return sqrtArray;23 24         }25     }
View Code
    • 首先ArrayList是一個非泛型集合,它需要的參數是object,那么我如果往集合里面裝配其它的類型,在編譯時也無法判斷錯誤(比如說我裝配一個字符串進去,完全是可以編譯成功的)。
    • 由于ArrayList需要的是一個object,那么在你將值類型裝配到集合中時,會進行隱式裝箱操作,在使用集合中的數據時,需要進行拆箱操作。從而影響應用程序的性能。(關于值類型裝箱請參考c#中的引用類型和值類型)。
    • 代碼可以可讀性差,完全看不明白ArrayList應該裝配什么類型。

下面來看看泛型是如何解決這些問題的:

 1     class Program 2     { 3         static void Main(string[] args) 4         { 5             List<double> array = new List<double>(); 6             array.Add(1); 7             array.Add(2); 8             array.Add(3); 9             List<double> resultArray = NumberSqrt(array);10             foreach (var item in resultArray)11             {12                 Console.WriteLine(item);13             }14         }15         public static List<double> NumberSqrt(List<double> array)16         {17             List<double> sqrtArray = new List<double>();18             foreach (var item in array)19             {20                 sqrtArray.Add(Math.Sqrt((double)(int)item));21             }22             return sqrtArray;23 24         }25 26     }
View Code
    • 由于List<double>只能裝配double,所以當你裝配其它的類型時編譯器會報錯,提高代碼的安全性。
    • 由于List<double>只能裝配double類型時,這樣的話就避免了編譯器隱式的裝箱和拆箱操作,提高應用程序的性能。
    • 一眼就可以看出集合需要裝配的類型,提高代碼的可讀性。
    • NumberSqrt方法在這里沒什么用去,如果你要寫一個算法,把NumberSqrt改為泛型方法:NumberSqrt<T>(比如說排序算法),可以實現算法重用。

     3,如何使用泛型:語法和規則

上面已經說了什么是泛型,以及為什么要用泛型,下面我們來聊聊如何使用泛型

    • 泛型的語法:泛型主要有泛型方法(例如:static void Swap<T>(ref T lhs, ref T rhs)),泛型接口( 例如: public interface IEnumerable<out T> : IEnumerable),泛型委托( 例如: public delegate void Action<in T>(T obj);)
    • 在FCL中內建了許多泛型的接口定義(常用的接口都在System.Collections.Generic),為了使泛型能夠正常的工作,微軟的開發人員將會做如下工作,
      • 創建新的IL指令,使之能夠識別類型參數。
      • 改變元數據的格式,使之能夠識別泛型參數和泛型方法。
    • 開放類型和封閉類型:當為一個泛型類型沒有指定實際的數據類型時,就稱為開放類型,例如List<T>,對于任何開放類型都不能創建該類型的實例,例如下面的代碼在運行是將會報錯未:經處理的異常:  System.ArgumentException: 無法創建 Consoleapplication2.Demo`1[T] 的實例,因為 Type.ContainsGenericParameters 為 True。
 1     public class Demo<T> { } 2     class Program 3     { 4         static void Main(string[] args) 5         { 6             object o = null; 7             Type t = typeof(Demo<>); 8             o = Activator.CreateInstance(t); 9         }10     }
View Code

               如果為泛型類型的所有類型實參傳遞的都是實際數據類型,類型就稱為封閉類型,CLR允許構造封閉類型的實例。

    • 泛型類型和繼承:泛型類型只是一個特殊的類型,所以它可以從其他任何類型派生。比如List<T>是從object派生的,那么List<String>也是從object派生的。換句話說,類型實參的指定和繼承層次結構沒有任何關系-理解這一點,有助于你判斷那些轉型是否能夠進行,哪些轉型是不能進行的。
    • 編譯器如何解決“代碼爆炸”的問題:在使用泛型類型或者方法方法時,Clr獲取IL代碼,用指定的類型實參進行替換。如果Clr為每種不同的類型/方法組合都生成不同的本地代碼,他可能會增大應用程序的工作集,從而影響性能。我們將這種現象稱為”代碼爆炸“。那么編譯器又是如何解決這個問題的呢?編譯器認為所有引用類型的實參是完全相同的,所以代碼能夠共享(為什么這么說呢?是因為所有引用類型的實參或者變量實際只是指向堆上的對象的指針,而對象的指針全部是以相同的方式來操操縱的)。但是如果某個類型實參是值類型的話,CLR就得專門為那個值類型生成本地代碼,這是值類型的大小不定。
    • 泛型接口:為什么要使用泛型接口呢?因為你每次試圖使用一個非泛型接口來操作一個值類型時,都會發生裝箱,從而失去編譯時的類型安全性。所以CLR提供了對泛型接口的支持。下面來看一個例子:
       1    // 摘要: 2     //     支持在泛型集合上進行簡單迭代。 3     // 4     // 類型參數: 5     //   T: 6     //     要枚舉的對象的類型。 7     public interface IEnumerator<out T> : IDisposable, IEnumerator 8     { 9         // 摘要:10         //     獲取集合中位于枚舉數當前位置的元素。11         //12         // 返回結果:13         //     集合中位于枚舉數當前位置的元素。14         T Current { get; }15     }
      View Code
    • 泛型委托:CLR之所以要支持泛型委托,主要目的是保證任何類型的對象都能以一種類型安全的方式傳給一個回調方法,并且保證了將一個值類型實例傳遞給一個回調方法時不執行任何裝箱處理。
    • 泛型方法:定義泛型類,結構或者接口時,這些類型中定義的任何方法都可引用由類型指定的一個類型參數。類型參數可以作為方法的參數/返回值,或者作為方法內部的一個局部變量來使用。下面來看一個例子:
       1  class Program 2     { 3         static void Main(string[] args) 4         { 5             MyClass<string> myclass = new MyClass<string>(); 6             myclass.ShowInfo("myClass"); 7         } 8     } 9 10     class MyClass<Ta>11     {12         public void ShowInfo(Ta a)13         {14             Type t = typeof(Ta);15             Console.WriteLine(t.FullName + "非泛型方法");16         }17         public void ShowInfo<Ta>(Ta a)18         {19             Type t = typeof(Ta);20             Console.WriteLine(t.FullName + "泛型方法");21         }22         public void ShowInfo<Tb>(Ta a, Tb b)23         {24             Type t = typeof(Tb);25             Console.WriteLine(t.FullName);26         }27     }
      View Code

       泛型方法的類型推斷:c#語法中包含大量"<"和">"符號,所以導致代碼的可讀性和可維護性降低了,所以為了改變這種情況,c#編譯器支持在調用一個方法時進行類型推斷。例如下面的代碼:myclass.ShowInfo("myClass", myclass);會調用ShowInfo<string>(string a, string b);

    • 可驗證性和約束:編譯器在編譯泛型代碼時,會對它進行分析,以確保代碼適用于當前已有或將來可能定義的任何類型。請查看下面的方法:
      1      public static Boolean MethodTakingAnyType<T>(T o) {2             T temp = o;3             Console.WriteLine(o.ToString());4             Boolean b = temp.Equals(o);5             return b;6         }
      View Code

      看這個方法里面有一個臨時變量temp。方法里面執行兩次變量賦值和幾次方法調用,無論T是值類型還是引用類型還是接口類型或者是委托類型這個方法都能工作。這個方法適用于當前存在的所以類型,也適用于將來可能定義的任何類型。比如你再看一下下面這個方法:

      1      public static T MethodTakingAnyType<T>(T o1,T o2) {2             if (o1.CompareTo(o2) < 0)3             {4                 return o1;5             }6             else {7                 return o2;8             }9         }
      View Code

      在編譯時會報如下錯誤(error CS0117:"T"不包含"CompareTo"的定義),因為并不是所有的類型都提供了CompareTo方法。那么在什么情況下T應該是什么類型呢?幸好,編譯器和CLR支持一個稱為約束的機制,可利用它使泛型變得真正有用!

      • 約束的語法:請看下面這個方法名字后面的where
        1 public static Boolean MethodTakingAnyType<T>(T o) where T : struct2         {3             T temp = o;4             Console.WriteLine(o.ToString());5             Boolean b = temp.Equals(o);6             return b;7         }
        View Code

        c#的where關鍵字告訴編譯器,為T指定的任何類型都必須是值類型。所以當你為T指定其它類型時,編譯器會報錯,例如你指定為string類型時(MethodTakingAnyType<string>("");)它會報錯誤    1    類型“string”必須是不可以為 null 值的類型才能用作泛型類型或方法

      • 主要約束:一個類型參數可以指定零個或一個主要約束(也就是第一個約束)。主要約束可以是一個引用類型,它標識了一個沒有密封的類,不能指定以下特殊類型:System.Object;System.Array;System.Delegate;System.MulticastDelegate;System.ValueType;System.Enum;
      • 次要約束:一個類型參數可以指定零個或多個次要約束。次要約束是一個接口類型,指定一個接口類型約束時,是告訴編譯器類型實參必須實現這個接口。還有一種次要約束稱為類型參數約束,有時也稱為裸類型約束,看下面的代碼
        1  public static Boolean MethodTakingAnyType<T, TBase>(T o) where T : TBase2         {3             T temp = o;4             Console.WriteLine(o.ToString());5             Boolean b = temp.Equals(o);6             return b;7         }
        View Code

        T類型參數由TBase類型單數約束,也就是說不管T為什么類型,都必須兼容于TBase指定的類型實參。

      • 構造器約束:一個類型參數可以指定零個或一個構造器約束。指定構造器約束相當于告訴編譯器一個指定的類型實參必須要實現了公共無參構造器。請看下面的的代碼:
        1       public static Boolean MethodTakingAnyType<T, TBase>(T o) where T : new()2         {3             T temp = o;4             Console.WriteLine(o.ToString());5             Boolean b = temp.Equals(o);6             return b;7         }
        View Code
      • 其它可驗證性的問題:1,泛型類型變量的轉型。下面的類型編譯時出錯,因為T可能為任何類型,無法保證能轉型成功!
        1     public static void MethodTakingAnyType<T, TBase>(T o)2         {3             int x = (int)o;4             string s = (string)o;5         }
        View Code

        2,將一個泛型類型變量設置為默認值:o = default(T);這樣的話,不管T為值類型還是引用類型都可以成功,如果T為引用類型時就設置為null,如果T為值類型時將默認值設為0;

        3,將一個泛型類型變量與Null進行比較:使用==或者=!將一個泛型類型變量于null進行比較都是合法的。但是如果T為值類型時,o永遠都不會為null查看下面的代碼:
        1        public static void MethodTakingAnyType<T, TBase>(T o)2         {3             if (o == null) { 4             //do something5             }6         }
        View Code

        4,將兩個泛型類型變量相互比較:如果T是值類型,下面的代碼就是非法的。

        1    public static void MethodTakingAnyType<T>(T o1,T o2)2         {3             if (o1 == o2) { 4             5             }6         }
        View Code

     4,泛型在使用過程的注意事項

    • 泛型不支持協變性
    • 缺乏操作符約束或者“數值”約束
    • 缺乏泛型屬性,索引器和其它成員類型

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩中国免费专区在线看| 一区三区二区视频| 欧美高清视频免费观看| 欧美激情视频在线| 欧美裸体视频网站| 亚洲视频在线观看| 国产91对白在线播放| 国产香蕉97碰碰久久人人| 亚洲欧美视频在线| 精品久久久久久中文字幕| 亚洲欧美激情精品一区二区| 日韩专区在线播放| 国产91精品不卡视频| 欧美香蕉大胸在线视频观看| 亚洲精品电影网在线观看| 日韩一区二区三区国产| 欧美性受xxxx白人性爽| 日韩国产一区三区| 亚洲综合一区二区不卡| 国产成人精品电影久久久| 在线播放国产一区中文字幕剧情欧美| 69国产精品成人在线播放| 最新国产精品拍自在线播放| 国产精品久久久久9999| 成人精品视频在线| 亚洲电影免费观看高清完整版| 久久成人在线视频| 欧美特黄级在线| 久久91精品国产91久久久| 日本久久久久久久久久久| 国外日韩电影在线观看| 91av在线视频观看| 欧美日韩裸体免费视频| 日韩视频永久免费观看| 奇米一区二区三区四区久久| 国产成人综合精品在线| 亚洲精品动漫久久久久| 欧美激情国产日韩精品一区18| 91产国在线观看动作片喷水| 久久久久久网站| 91沈先生在线观看| 欧美亚洲另类激情另类| 国产精品白嫩美女在线观看| 成人春色激情网| 亚洲精品丝袜日韩| 亚洲综合中文字幕68页| 亚洲free性xxxx护士hd| 欧美日韩黄色大片| 久久久91精品国产一区不卡| 精品国产成人av| 亚洲国产成人爱av在线播放| 亚洲国产中文字幕在线观看| 91视频免费在线| 人人做人人澡人人爽欧美| 亚洲免费成人av电影| 精品久久久久久国产| 成人免费观看49www在线观看| 91日韩在线视频| 精品国内产的精品视频在线观看| 中文字幕日韩欧美| 青青草99啪国产免费| 欧美亚洲第一区| 日本成熟性欧美| 亚洲精品自产拍| 国产精品美女www爽爽爽视频| 国产精品欧美日韩| 中文字幕日韩欧美精品在线观看| 国产精品日韩电影| 国产精品白丝av嫩草影院| 久久99热这里只有精品国产| 中文日韩电影网站| 亚洲精品mp4| 日韩欧美在线视频免费观看| 日韩欧美在线视频免费观看| 亚洲一区二区三区777| 国产精品黄色av| 日韩av电影在线播放| 国产亚洲一区二区精品| 国产视频精品va久久久久久| 91精品美女在线| 国产精品视频免费在线观看| 激情久久av一区av二区av三区| 91精品视频在线| 欧美一级bbbbb性bbbb喷潮片| 国产亚洲精品久久久优势| 国产美女搞久久| 国产日韩精品综合网站| 国产91露脸中文字幕在线| 国产精品精品视频| 国产综合在线视频| 国产精品国产三级国产专播精品人| 亚洲丝袜av一区| www.日韩系列| 日韩精品中文字幕在线播放| 最近2019中文字幕第三页视频| 色综合伊人色综合网站| 欧美国产视频日韩| 日韩在线观看网址| 九九精品在线视频| 欧美中文在线观看国产| 国产精品99一区| 狠狠综合久久av一区二区小说| 欧美一级免费看| 亚洲一区二区三区在线视频| 国产一区二区色| 欧美日韩国产一区中文午夜| 欧美日在线观看| 亚洲奶大毛多的老太婆| 人九九综合九九宗合| 992tv成人免费影院| 国产精品欧美在线| 在线电影中文日韩| 亚洲第一视频网站| 国产精品视频地址| 在线观看亚洲区| 欧美小视频在线观看| 久色乳综合思思在线视频| 亚洲在线观看视频网站| 在线a欧美视频| 97香蕉超级碰碰久久免费软件| 日韩电影中文字幕在线观看| 成人免费大片黄在线播放| 亚洲欧洲在线免费| 亚洲999一在线观看www| 欧美一区二区三区艳史| 久久视频免费观看| 91久久久久久| 久久精品99久久香蕉国产色戒| 国产精品免费久久久久影院| 国产精品午夜视频| 亚洲国产精久久久久久| 国产精品视频永久免费播放| 丝袜亚洲欧美日韩综合| 国产日韩欧美一二三区| 亚洲精品国产拍免费91在线| 亚洲国产精品99久久| 日韩精品有码在线观看| 国产成人精品av| 亚洲成人激情在线观看| 国产精品人人做人人爽| 精品欧美一区二区三区| 狠狠躁夜夜躁久久躁别揉| 国产日产欧美a一级在线| 国产日韩欧美成人| 在线精品国产欧美| 国产亚洲在线播放| 亚洲free嫩bbb| 欧美日韩免费网站| 国产69精品久久久久99| 亚洲free性xxxx护士hd| 国产成人91久久精品| 国产一区二区三区高清在线观看| 欧美乱人伦中文字幕在线| 国产在线视频91| 91在线无精精品一区二区| 91久久久久久久久| 国产精品高潮呻吟久久av无限| 亚洲 日韩 国产第一| 亚洲第一页自拍| 日韩精品视频在线观看网址| 亚洲欧美日韩中文在线| 日韩美女免费线视频| 一本色道久久综合亚洲精品小说| 欧美www在线|