<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      記錄點滴收獲,匯聚知識樂園

      腳步無法到達的地方,目光可以到達;目光無法到達的地方,夢想可以到達

      導航

      泛型入門

      定義:

      所謂泛型,即通過參數化類型實現在同一份代碼上操作多種類型的數據,泛型編程是一種范式的轉化(在這里體現為類型的晚綁定),他利用參數化類型,將類型抽象化,從而實現代碼的靈活復用,精簡代碼。

      泛型的好處:

         a.減少了對對象進行裝箱和拆箱所導致的性能成本,提高了效率。

         b.賦予了代碼更強的類型安全。

         c.實現了更為靈活的代碼復用。

      注:1.NET參數化類型不是編譯(JIT編譯)時被實例化,而是運行時被實例化。

             2.由微軟在產品文檔中提出建議,所有的泛型參數名稱都以T開頭,這是作為一種編碼的通用規范。

      在定義泛型時,可以對客戶端代碼在實例化類時用于類型參數的類型施加一些限制,如果客戶端代碼嘗試使用某個約束所不允許的類型來實例化類,則會產生編譯錯誤,這些限制稱為約束,約束是使用where關鍵字實現的。

      每個泛型參數至少擁有一個主約束,泛型的主約束是指指定泛型參數必須是或者繼承自某個引用類型。每個泛型參數可以具有多個次約束,次約束和主約束的語法基本相同,但它規定的是某個泛型參數必須實現所有次約束指定的接口。

      下面列出了五種類型的約束:

         T:struct    類型參數必須為值類型,可以指定除 Nullable 以外的任何值類型。

         T:class     類型參數必須為引用類型,包括類、接口、委托、和數組。

         T:new()    類型參數必須具有無參公共構造函數,當與其他約束一起使用時,new() 約束必須最后指定。

         T:<基類名>  類型參數必須為指定的基類或繼承自該基類的子類。

         T:<接口名稱> 類型參數必須是指定的接口或實現指定的接口。可以指定多個接口約束。約束接口也可以是泛型的。

         T:U              為 T 提供的類型參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束.

      泛型的編譯和運行機制

        C#泛型能力由CLR在運行時支持,區別于C++編譯時模板的機制,和java編譯時的“搽拭法”,這事得泛型能力可以在各個支持CLR語言之間進行無縫的互操作。C#泛型代碼在編譯為IL代碼和元數據時,采用特殊的占位符來表示泛型實例,并用專有的IL指令來支持泛型操作,而真正的泛型實例化工作發生在JIT編譯時。

      這里我們對三種語言對泛型的支持做一個對比:

      C++的模板機制:C++在編譯時會根據每一個傳入的類型參數創建一份基于特定類型的類型碼,因此如果有多個類型參數傳入,編譯時就會生成多份相似的類型碼,容易導致代碼膨脹。因此C++的泛型只是實現了在源代碼層面的復用,并沒有實現IL層面的代碼復用。

      C#:一輪編譯時,編譯器會依據泛型參數的約束條件產生一份能進行某些特定操作(比如調用構造器生成類型實例,調用某一方法等)的“泛型版”的IL代碼和元數據,并不進行泛型類型的實例化,但此時可以確定泛型類型可以進行哪些操作了,T在中間只是充當占位符,這一點可以通過下面展示的一份泛型的IL代碼來證明。只有JIT編譯時CLR才會將滿足泛型約束的類型實例傳入,并針對不同的類型產生不同的類型碼,在類型碼產生的過程中,CLR進行了許多的優化:1.CLR為所有引用類型的類型參數產生一份共同的一份類型碼,所有的引用類型共用這一份類型碼。2.對于每一個不同的值類型,CLR將為其產生一份獨立的類型碼。另外,C#泛型類型攜帶有豐富的元數據,因此C#的泛型類型可以應用于強大的反射技術。

       

      java:java在進行第一階段的編譯時,將泛型類型用Object類型進行替換,因此類型參數實例化的時候需要進行大量的裝箱和拆箱工作,但是這些工作并不需要我們去做,編譯器會自動的進行這些工作,性能成本比較高。本質上講并沒有實現真正意義上的泛型,是編譯器的一種欺騙行為。

      下面通過具體的例子來一點一點的深入泛型。

      我們來實現一個最簡單的冒泡排序(Bubble Sort)算法,如果你沒有使用泛型的經驗,我猜測你可能會毫不猶豫地寫出下面的代碼來,因為這是大學教程的標準實現:

      public class Sort{

      public void BubbleSort(int[] array) {  
          for (int i = 0; i <= array.Length - 2; i++) {
              for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j] < array[j - 1]) {
                      int temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }
          }
        }

      }

      后來我們需要對一個byte類型的數組進行排序,而上面排序的方法只能對int型的數組進行排序,因此我們不得不重寫代碼:

      public class Sort{

      public void BubbleSort(byte[] array) {  
          for (int i = 0; i <= array.Length - 2; i++) {
              for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j] < array[j - 1]) {
                      byte temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }
          }
        }

      }

      現在我們將int[]和byte[]用占位符來替代,形成一種通用的代碼:

      public class Sort{

      public void BubbleSort(T[] array) {  
          for (int i = 0; i <= array.Length - 2; i++) {
              for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j] < array[j - 1]) {
                      T temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }
          }
        }

      }

      但是我們又發現了一個問題:當我們定義一個類,而這個類需要引用它本身以外的其他類型時,如何將這個類型參數傳進來了,此時就需要使用一種特殊的語法來傳遞這個T占位符,我們在類名稱的后面加了一個尖括號,使用這個尖括號來傳遞我們的占位符,也就是類型參數。

      public class Sort<T>{

      public void BubbleSort(T[] array) {  
          for (int i = 0; i <= array.Length - 2; i++) {
              for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j] < array[j - 1]) {
                      T temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }
          }
        }

      }

      使用的時候我們就可以這樣使用:

      public class Test{

        public static void Main(){

           Sort<int> sorter = new Sort<int>();
           int[] array = { 8, 1, 4, 7, 3 };
           sorter.BubbleSort(array);

        }

      }

      上面所講述的一切都是一個泛型的典型應用,可以看到,通過使用泛型,我們極大地減少了重復代碼,使我們的程序更加清爽,泛型類就類似于一個模板,可以在需要時為這個模板傳入任何我們需要的類型。

      下面我們來談一下泛型約束

      實際上,如果你運行一下上面的代碼,發現他們無法通過編譯,為什么了,就是因為有了T的存在,T是晚綁定的,因此在編譯時編譯器還無法得知T的實例是什么,更不用說未來傳進來的類型實例是采用什么樣的標準來進行大小的比較的,下面我們舉例說明:

      假如我們有一個自定義的類Book,它定義了書,它包含兩個私有字段_id和_title,兩個外部屬性:ID和Title,以及兩個構造器

      public class Book

      {

         private int _id;

         private string _title;

         public Book(){ }

         public Book(int id,string title)

          {

              this._id=id;

              this._title=title

          }

          public int ID

          {

             get{return _id;}

             set{_id=value;}

          }  

          public string  Title

          {

             get{return _title;}

             set{_title=value;}

          }

      }

      現在我們創建一個Book型的數組,然后用Sort類中的方法對其進行排序:

      class Test{

         static void Main()

         {

             Book[] bookArray=new Book[2];

              Book book1=new Book(1,"guowenhui");

              Book book2=new Book(2,"dongyaguang");

              bookArray[0]=book1;

              bookArray[1]=book2;

              Sort<Book>  sort=new Sort<Book>;

              Sort.BubbleSort(bookArray);

              foreach (Book b in bookArray) {
              Console.WriteLine("Id:{0}", b.Id);
             Console.WriteLine("Title:{0}\n", b.Title);
            }

         }

      }

      可能你覺得這樣很好,基本沒什么問題,但是我們來看看BubbleSort()方法的實現,我截取關鍵的一段:

       for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j] < array[j - 1]) {
                      T temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }

      大家會看到if語句里面會對數組里面的兩個元素進行比較,那么問題就出在這兒,由于類型參數的實例化是晚綁定的,因此在C#編譯器編譯好泛型類的時候,這時還并不知道未來發生在JIT編譯階段類型實例化過程會傳進來什么樣的類型參數,但是我們又必須在泛型類中對兩個不確定類型的對象進行大小的比較工作,而且這個事情是在編譯時就確定下來的,這就很讓人糾結了,萬一在類型實例化時傳進來一個我們無法對對象進行比較的類型參數怎么辦?怎么解決了,唯一的辦法就是對傳進來的類型參數加以限制,不是任何類型參數都可以被傳進來的,必須滿足了一定的條件,而在這里我們的限制條件就是必須能進行大小的比較。我們的類型是Book,那么我要問,book1和book2到底誰大了,有的人說book1大,有的人說book2大,這里就涉及到一個判斷依據的問題。那么如何來實現這種比較了,答案是:讓需要進行比較的類實現IComparable接口。也就是說只有實現了IComparable接口的類型才能作為類型參數被傳入,即我們需要對傳入參數的類型進行一些約束,這就是我們要講的泛型約束,在本例中我們實現的是接口約束。

      接下來我們就讓Book類來實現IComparable接口,即在類的內部定義一個比較的標準,我們這里采用的標準是比較ID:

      public class Book : IComparable

      {

         public int CompareTo(object obj)  //實現接口

         {

           Book book2=(Book)obj;   

           return this.ID.CompareTo(book2.ID);

         }

         private int _id;

         private string _title;

         public Book(){ }

         public Book(int id,string title)

          {

              this._id=id;

              this._title=title;

          }

          public int ID

          {

             get{return _id;}

             set{_id=value;}

          }  

          public string  Title

          {

             get{return _title;}

             set{_title=value;}

          }

      }

      現在我們應該可以進行比較了吧,還不行,因為Sort類是一個泛型類編譯時編譯器對于傳入該類的類型參數一無所知(類型的晚綁定),明確的說需要等到運行時才能確定參數,也不會做任何猜想,雖然我們知道Book類實現了

      IComparable接口,但編譯器并不知道,因此我們必須Sort<T>類(即告訴JIT編譯器),它所接受的類型參數必須實現了IComparable接口,這便是泛型約束,下面我們來對泛型類Sort<T>的傳入參數進行約束,同時我們對比較大小的方法進行一些修改。

      public class Sort<T> where T : IComparable

      {

       public void BubbleSort(T[] array) {  
          for (int i = 0; i <= array.Length - 2; i++) {
              for (int j = array.Length - 1; j >= 1; j--){          

                  if (array[j].CompareTo(array[j-1])<0) {
                      T temp = array[j];
                      array[j] = array[j - 1];
                      array[j - 1] = temp;
                  }
              }
          }
        }

      }

      此時我們再次運行下面定義的代碼

      class Test{

         static void Main()

         {

             Book[] bookArray=new Book[2];

              Book book1=new Book(1,"guowenhui");

              Book book2=new Book(2,"dongyaguang");

              bookArray[0]=book1;

              bookArray[1]=book2;

              Sort<Book>  sort=new Sort<Book>();

              Sort.BubbleSort(bookArray);

              foreach (Book b in bookArray) {
              Console.WriteLine("Id:{0}", b.ID);
             Console.WriteLine("Title:{0}\n", b.Title);
            }

            Console.ReadLine();

         }

      }

      會得到結果:

      ID:1

      Title:guowenhui

      ID:2

      Title:dongyaguang

      下面是完整的代碼:

       

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      namespace ConsoleApplication1
      {
      public class Book : IComparable
      {
      public int CompareTo(object obj) //實現接口
      {
      Book book2 = (Book)obj;
      return this.ID.CompareTo(book2.ID);
      }
      private int _id;
      private string _title;
      public Book() { }
      public Book(int id, string title)
      {
      this._id=id;
      this._title = title;
      }
      public int ID
      {
      get { return _id; }
      set { _id = value; }
      }
      public string Title
      {
      get { return _title; }
      set { _title = value; }
      }
      }

      public class Sort<T> where T : IComparable
      {
      public void BubbleSort(T[] array)
      {
      for (int i = 0; i <= array.Length - 2; i++)
      {
      for (int j = array.Length - 1; j >= 1; j--)
      {
      if (array[j].CompareTo(array[j - 1]) < 0)
      {
      T temp = array[j];
      array[j] = array[j - 1];
      array[j - 1] = temp;
      }
      }
      }
      }
      }
      class Test
      {
      static void Main()
      {
      Book[] bookArray=new Book[2];
              Book book1=new Book(1,"guowenhui");
      Book book2=new Book(2,"dongyaguang");
      bookArray[0]=book1;
      bookArray[1]=book2;
      Sort<Book> sort = new Sort<Book>();
      sort.BubbleSort(bookArray);
      foreach (Book b in bookArray)
      {
      Console.WriteLine("Id:{0}", b.ID);
      Console.WriteLine("Title:{0}\n", b.Title);
      }
      Console.ReadLine();
      }
      }
      }

       

      泛型接口

       

      沒有泛型接口,每次試圖使用一個非泛型接口(如IComparable)來操縱一個值類型時,都會進行裝箱,而且會丟失編譯時的類型安全性。這會嚴重限制泛型類型的應用。所以,CLR提供了對泛型接口的支持。一個引用類型或值類型為了實現一個泛型接口,可以具體指定類型實參;另外,一個類型也可以保持類型實參的未指定狀態來實現一個泛型接口。來看一些例子:

       

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Text;
      using System.Threading;
      namespace ConsoleApplication1
      {
      interface ITest<T, V> //泛型接口的定義
      where T : class
      where V : struct
      {
      void Print(T t, V v);
      }

      class TestA //自定義引用類型
      {
      private string _name;
      public string Name
      {
      set { _name = value; }
      get { return _name; }
      }
      }
      struct TestB //自定義值類型
      {
      private int _age;
      public int Age
      {
      get { return _age; }
      set { _age = value; }
      }
      }

      class TestC : ITest<TestA,TestB> //繼承并實現接口
      {
      public void Print(TestA A, TestB B)
      {
      Console.WriteLine(A.Name + " is " + B.Age);
      }
      }

      class Program
      {
      static void Main()
      {
      TestA testA = new TestA();
      testA.Name = "guowenhui";
      TestB testB = new TestB();
      testB.Age = 21;
      TestC testC = new TestC();
      testC.Print(testA, testB);
      Console.ReadLine();
      }
      }
      }





      posted on 2011-12-18 15:03  guowenhui  閱讀(2124)  評論(6)    收藏  舉報

      主站蜘蛛池模板: 华人在线亚洲欧美精品| 色一情一乱一区二区三区码| 极品无码人妻巨屁股系列| 亚洲人成网网址在线看| 亚洲国产精品日韩AV专区| 亚洲精品国偷拍自产在线观看蜜臀| 伊人久久大香线蕉网av| 国产一区二区三区尤物视频| 黑人玩弄人妻中文在线| 色综合欧美亚洲国产| 国内熟妇与亚洲洲熟妇妇| 久久天天躁夜夜躁一区| 男人狂桶女人出白浆免费视频| 免费国产高清在线精品一区| 国产在线观看码高清视频| 佛教| 成人伊人青草久久综合网| 亚洲欧洲日韩国内精品| 丰满少妇人妻久久久久久| 人人妻人人澡人人爽| 极品白嫩少妇无套内谢| 亚洲精品久久国产高清| av一区二区中文字幕| 精品日韩人妻中文字幕| 国产又大又粗又爽的毛片| 色道久久综合亚洲精品蜜桃| 四虎在线播放亚洲成人| 在线亚洲人成电影网站色www| 国产专区一线二线三线码| 漂亮人妻中文字幕丝袜| 屯昌县| 国产亚洲精品久久综合阿香| 无码中文字幕人妻在线一区| 风韵丰满熟妇啪啪区老熟熟女| 中美日韩在线一区黄色大片| 欧美牲交a欧美牲交aⅴ一| 国产在线精品福利91香蕉| 婷婷色香五月综合缴缴情香蕉| 无码人妻丰满熟妇区bbbbxxxx| 亚洲精品日韩久久精品| 亚洲av午夜成人片|