程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C# 2.0泛型類的創建和使用

C# 2.0泛型類的創建和使用

編輯:關於C#

"一次編碼,多次使用",這就是引入泛型的根源。在以前的C++中 稱為模板,C#泛型通過算法和數據結構支持獨立編碼。例如,泛型列表意味著, 你不必再重寫一個強類型集合。在本文中,作者將向你展示定義和使用泛型是多 麼容易的事情-請注意,長期以來泛型一直被認為是最高級和最困難的術語。

一、簡介

泛型現在在任何一種語言中都被認為是一個高級的強有 力的術語。當我在C++中第一次接觸模板時,我對之有些疑惑。之後,我讀了 Bjarne Stroustrop的《The Design and Evolution of C++》,才發現模板的使 用就象C中的宏和用之來取代的簡單串替換模板一樣容易。其實,模板和泛型是 相同的東西-盡管它們的實現稍微不同。

C#泛型支持在使用點處才定義算 法及其數據類型。在C#的一些早期版本中,我們可以證明沒有泛型也可以工作, 因為每種類型都是派生於一個公共基類型-object。這意味著程序員可以基於 object類型定義一個棧類並且把一切東西放到該棧上(因為一切都派生於object) 。然而,一個object棧意味著,Customer對象,Integer對象以及假想的對象都 能被放置到同一個棧的實例上。結果是,開發者要子類化數據類型來把數據類型 綁定到他們要與之交互的東西上去。例如,在編寫定制的商業對象時,我們就建 議定義派生於System.Collections.CollectionBase的強類型集合。原因很簡單 :基於object定義一切被認為是弱類型定義。

業界的高手們在數十年前 就確信強類型優於弱類型,所以.NET最終支持強類型,這看上去是很自然的事情 。強類型算法當然建議類型化參數-這正是我們在泛型中所用的東西。

十 幾年來,我們一直在使用字母T作為類型化參數的名字。這樣,在任何泛型類使 用者所提供的數據類型的地方,你都能夠找到T。使用泛型的關鍵僅僅是提供這 個T。定義泛型的關鍵在於實現一個方法或類,並且用特定數據類型來替換掉T。

C#中的泛型支持另外一些提煉。例如,一個方法或類可以有多個參數化 的類型並且C#泛型還支持WHERE約束-它用來具體要求類型化參數的類型。例如, 如果一個泛型類型必須實現接口IDisposable,那麼C#泛型是支持實現這一限制 的。在文章的最後我們還要看一下約束問題。

閒話少說,讓我們言歸正 傳。

二、使用泛型集合

有些人問我"面向對象編程(OOP) 的承諾在哪裡?",我的回答是應該從兩個方面來看OOP:你所使用的OOP和 你創建的OOP。如果我們簡單地看一下如果沒有如例如Microsoft的.NET, Borland的VCL,以及所有的第三方組件這樣的OO框架,那麼很多高級的應用程序 幾乎就無法創建。所以,我們可以說OOP已經實現了它的承諾。不錯,生產好的 OOP代碼是困難的並且可能是極具挫敗性的;但是記住,你不必須一定要通過OOP 來實現你的目標。因此,下面首先讓我們看一下泛型的使用。

當你用 Visual Studio或C# Express等快速開發工具創建工程時,你會看到對於 System.Collections.Generic命名空間的參考引用。在這個命名空間中,存在若 干泛型數據結構-它們都支持類型化的集合,散列,隊列,棧,字典以及鏈表等 。為了使用這些強有力的數據結構,你所要做的僅是提供數據類型。

列 表1顯示出我們定義一個強類型集合的Customer對象是很容易的。

列表1 這個控制台應用程序包含一個Customer類和一個基於List<T>的強類型集 合Customers。

using System;
using System.Collections.Generic;
using System.Text;
namespace Generics{
 class Program{
  static void Main(string[] args){
   List<Customer> customers = new List<Customer>();
   customers.Add(new Customer ("Motown-Jobs"));
   customers.Add(new Customer ("Fatman's"));
   foreach (Customer c in customers)
   Console.WriteLine(c.CustomerName);
    Console.ReadLine();
  }
 }
 public class Customer {
  private string customerName = "";
  public string CustomerName{
   get { return customerName; }
    set { customerName = value; }
  }
  public Customer (string customerName){
   this.customerName = customerName;
  }
 }
}

注意,我們有一個強類型集合- List<Customer>-對這個集合類本身來說不需要寫一句代碼。如果我們想 要擴展列表customer,我們可以通過從List<Customer>繼承而派生一個新 類。

三、實現一個泛型類

一種合理的實現某種新功能的方法是在 原有的事物上進一步構建。我們已經了解強類型集合,並知道一種不錯的用來構 建泛型類的技術是使用一個特定類並刪除數據類型。也就是說,讓我們定義一個 強類型集合CustomerList,並且來看一下它要把什麼東西轉化成一個泛型類。

列表2定義了一個類CustomerList。後面的部分把CustomerList轉化成 List<T>。

列表2定義類CustomerList:

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class CustomerList : CollectionBase{
  public CustomerList() { }
  public Customer this[int index]{
   get { return (Customer)List [index]; }
   set { List[index] = value; }
  }
   public int Add(Customer value)
  {return List.Add(value);}
 }
}

四、定義類頭

如果我們定義一個泛型類, 我們需要把類頭轉化成一個泛型類。所有我們需要做的是命名參數並且把類名改 成某種泛型。List<T>只有一個參數T,並且因為我們在以一種向後兼容的 方式工作,所以我們知道類名是List。列表3顯示出列表2中類的新類頭。

列表3 一個泛型類頭顯示出參數化的參數T。

using System;
using System.Collections;
using System.Text;
namespace Generics{
public class List<T> : CollectionBase {}

五、實現泛型字段

如果我們需要把任何字段轉換成泛 型字段,我們將只需簡單地把它們的類型改變成T(或該字段所描述的任何參數) 。泛型List不需要任何字段,但是假定存在一個私有的整型字段叫foo-我們將把 它泛型化。我們將如下重新定義它:

private T foo;

當參數T被填充到類中時,List T也將因foo被填充。

六、定義泛型方法

接下來,我們為所需要的參數化類型定義其它 一些特性。這包括屬性,方法,和事件。在我們的實例中,在Customer出現的每 一處,我們都用參數T替換它。完成後的泛型列表類顯示於列表4中。

列 表4 一個基於System.Collections.CollectionBase的輕量級的參數化泛型列表 類。

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class List<T> : CollectionBase {
  public List(){ }
   public T this[int index] {
   get { return (T)List[index]; }
   set { List[index] = value; }
  }
  public int Add(T value) {
   return List.Add(value);
  }
 }
}

為了測試該定制列表,注釋掉使用 System.Collections.Generic命名空間一句並且把列表4中的List<T>使用 在列表1的代碼中;它將以同樣的方式工作。

全面地修改.NET的 List<T>是不必要的而且它也包含遠比我們的示例多得多的特性;但是列 表4顯示出這種機制對於定義定制泛型類是多麼容易。

七、增加類型約束

最後要討論的是約束問題。約束被應用於類或其它特性上並且使用下面 的語法:

Where T : constraint_type

例如,任何 我們想要通過using語句所使用的,如一個SqlDataReader,必須實現 Idisposable接口。這是因為如下方式使用的using語句:

using (Form f = new Form()){...}

就象一個try..finally塊一樣工作 -總是清除新創建的資源。其工作原理很簡單,只需要CLR針對在該using語句中 創建的對象發出一個到IDisposable.Dispose的調用即可。例如,在上面這一句 中,一個新的表單被創建,並且在using語句退出之前即調用Form.Dispose。

要對一個泛型類施加以確保該類實現了接口IDisposable,我們將添加先 行詞where T:Idisposable。在列表4中的泛型列表上施加約束後,我們將重新修 改列表4如下面的列表5所示。

列表5 增加一個約束到泛型類以確保我們 的List<T>中的所有的值T實現接口Idisposable。

using System;
using System.Collections;
using System.Text;
namespace Generics{
 public class List<T> : CollectionBase where t : IDisposable{
  public List(){ }
  public T this[int index]{
   get { return (T)List[index]; }
   set { List[index] = value; }
  }
  public int Add(T value){return List.Add(value);}
 }
}

先行詞where的值可以是類,接口,結構,實現一個無參的公共 構造器或有一個特定的基類的類。詳見有關幫助文檔。

八、總結

泛型的設計是用來減少你重復實現的代碼的次數-只需改變數據類型即可。因為 抽象數據結構,如隊列,棧和列表皆是典型的數據結構,所以存在針對這些東西 的泛型類完全可以理解。你可以從.NET中派生大量的值-通過使用現有的泛型類 ,如在System.Collections.Generic命名空間中的那些。

可以肯定,在 一段相當長的時間裡,泛型將會象模式和重構等革新一樣對開發帶來越來越大的 價值,而且新的數據結構能被轉換成可重用的如泛型等的代碼元素。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved