深入理解C#中的泛型(一)

來源:互聯網
上載者:User

標籤:理解   public   arp   string類   this   compareto   說明   his   提醒   

為什麼要有泛型?

  請大家思考一個問題:由你來實現一個最簡單的冒泡排序演算法。假設沒有使用泛型的經驗。可能會毫不猶豫的寫出下面代碼:

public class SortHelper    {        //參數為int數組的冒泡排序        public void BubbleSort(int[] array)        {            int length = array.Length;            for (int i = 0; i <= length - 2; i++)            {                for (int j = length - 1; j >= 1; j--)                {                    //對兩個元素進行交換                    if (array[j] < array[j - 1])                    {                        int temp = array[j];                        array[j] = array[j - 1];                        array[j - 1] = temp;                    }                }            }        }    }
  如今通過對這個程式進行一個簡單的測試:
      static void Main(string[] args)        {            #region  沒有泛型前的示範            SortHelper sorter = new SortHelper();            int[] arrayInt = { 8, 1, 4, 7, 3 };            //對int數組排序            sorter.BubbleSort(arrayInt);            foreach (int i in arrayInt)            {                Console.Write("{0} ", i);            }            Console.ReadLine();            #endregion        }
  我們發現它執行良好,欣喜的覺得這便是最好的解決方式了。直到不久後,須要對一個byte類型的數組進行排序。而上面的排序演算法僅僅能接受一個int類型的數組。C#是一個強型別的語言。無法在一個接受int數群組類型的地方傳入一個byte數組。只是沒關係,如今看來最快的解決方案是把代碼複製一遍,然後將方法的簽名改一下:
 public class SortHelper    {        //參數為byte數組的冒泡排序        public void BubbleSort(byte[] array)        {            int length = array.Length;            for (int i = 0; i <= length - 2; i++)            {                for (int j = length - 1; j >= 1; j--)                {                    //對兩個元素進行交換                    if (array[j] < array[j - 1])                    {                        byte temp = array[j];                        array[j] = array[j - 1];                        array[j - 1] = temp;                    }                }            }        }    }
  好了,再一次解決這個問題。可通過認證觀察我們發現,這兩個方法除了傳入的參數類型不同外。方法的實現非常相似,是能夠進行進一步抽象的。於是我們思考,為什麼在定義參數的時候不用一個預留位置T取代呢?T是Type的縮寫。能夠代表不論什麼類型,這樣就能夠屏蔽兩個方法簽名的差異:    
   public class SortHelper<T>    {        //參數為T的冒泡排序        public void BubbleSort(T[] array)        {            int length = array.Length;            for (int i = 0; i <= length - 2; i++)            {                for (int j = 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起一個正式的名稱。在.Net中叫做“類型參數”。類型參數約束

  實際上,如果執行上面的代碼就會發現,它連編譯都通只是去,為什麼呢?考慮這樣一個問題:如果我們自己定義一個類型。名字叫做Book,它包括兩個欄位:一個是int類型的Price代表書的價格;一個是string類型的Title,代表書的標題:

public class Book     {        //價格欄位        private int price;        //標題欄位        private string title;        //建構函式        public Book() { }        public Book(int price, string title)        {            this.price = price;            this.title = title;        }        //價格屬性        public int Price        {            get { return this.price; }        }        //標題屬性        public string Titie        {            get { return this.title; }        }    }
  如今建立一個Book類型的數組,然後使用上面定義的泛型類對它進行排序,代碼應該像以下這樣:
            Book[] bookArray = new Book[2];            Book book1 = new Book(30, "HTML5解析");            Book book2 = new Book(21, "JavaScript實戰");            bookArray[0] = book1;            bookArray[1] = book2;            SortHelper<Book> sorterGeneric = new SortHelper<Book>();            sorterGeneric.BubbleSort(bookArray);            foreach (Book b in bookArray)            {                Console.WriteLine("Price:{0}", b.Price);                Console.WriteLine("Title:{0}", b.Titie);            }
  這時問題來了。既然是排序。就免不了比較大小,那麼如今請問:book1和book2誰比較大?張三能夠說book1大,由於它的Price是30,;而李四能夠說book2大,由於它的Title是“J”開頭的,比book1的“H”靠後。說了半天,問題在於不確定按什麼規則排序。
  既然不知道,那我們就給Book定義一種定序(按價格排序),我們聲明一個用於比較的介面:
 public interface IComparable    {        int CompareTo(object obj);    }
  讓Book類型實現這個介面:
public class Book : IComparable    {        //CODE:上面的實現略        public int CompareTo(object obj)        {            Book book2 = (Book)obj;            return this.Price.CompareTo(book2.Price);        }    }
  既然我們如今已經讓Book類實現了IComparable介面,那麼泛型類應該可以工作了吧?不行的,還要記得,泛型類是一個模板類。它對在運行時傳遞的類型參數是一無所知的。也不會做不論什麼的推測。所以須要我們告訴泛型類SortHelper<T>,它所接受的T類型參數必須可以進行比較,也就是說必須實現IComparable介面。我們把對T進行約束這樣的行為稱:泛型參數約束。

  為了要求類型參數T必須實現IComparable介面,須要像以下這樣又一次定義:

public class SortHelper<T> where T : IComparable    {        //參數為T的冒泡排序        public void BubbleSort(T[] array)        {            int length = array.Length;            for (int i = 0; i <= length - 2; i++)            {                for (int j = 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;                    }                }            }        }    }
  上面的定義說明了類型參數T必須實現IComparable介面。否則將無法通過編譯。由於如今T已經實現了IComparable介面,而數組array中的成員是T的執行個體。所以當在array[i]後面點擊小數點“.”時,VS能夠智能提醒出T是IComparable的成員,也就是CompareTo()方法。

深入理解C#中的泛型(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.