程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C# 編程語言的未來功能

C# 編程語言的未來功能

編輯:關於C語言
Prashant Sridharan
Microsoft Corporation
2003年3月
適用於:
   Microsoft® Visual C#(TM)

摘要:Microsoft Corporation 正在開發 C# 語言的下一個主要版本。本文介紹了四種主要的新功能,即泛型、迭代程序、匿名方法和局部類型。

目錄
簡介
泛型
迭代程序
匿名方法
局部類型
符合標准
可用性
更多信息
簡介
C# 是創新性的新式編程語言,它巧妙地結合了最常用的行業語言和研究語言中的功能。在保持 C# 設計思想不變的同時,Microsoft 在 C# 語言中引入了幾種潛在的新功能,提高了開發人員在語言構造方面的效率。

Microsoft C#
自 2001 年 2 月 C# 問世以來,很多開發人員已經開始使用 C# 編程語言來構建軟件。而 Microsoft 自身也使用 C# 構建了幾種正式的應用程序,包括 .Net Framework、MSN Web 屬性和 Tablet PC SDK。由此可見,C# 是一種適用於構造高品質商業軟件的語言。

C# 語言中的許多功能是基於以下四種不同設計目標而創建的:

統一的類型系統以及簡化值類型和引用類型在 C# 語言中的用法。
通過 XML 注釋、特性、屬性、事件和委托等功能建立基於組件的設計。
借助 C# 語言的獨特功能(包括安全的指針操作、溢出檢查等)建立實用的開發人員控制功能。
建立諸如 foreach 和 using 語句這樣的實用語言構造,提高開發人員的效率。
在 C# 語言的“Visual Studio for Yukon”版本中,Microsoft 計劃通過將廣泛的研究語言和行業語言中的各種功能結合在一起建立一種簡潔、實用的語法。這些語言功能包括泛型、迭代程序、匿名方法和局部類型。

潛在的未來功能
實際上,C# 的未來創新功能主要基於統一的類型系統、基於組件的開發、開發人員控制功能和實用的語言構造。下面總結了 Microsoft 計劃在 C# 語言的下一個主要版本中提供的四種主要的新功能。這些功能的設計尚未完成,Microsoft Corporation 歡迎廣大的開發人員針對這些功能發表評論。

泛型
隨著項目變得越來越復雜,程序員日益需要一種方法來更好地重復使用和自定義他們現有的基於組件的軟件。為了實現在其他語言中重復使用高級代碼,程序員通常要使用一種名為“泛型”的功能。C# 將包括一種安全且高效的泛型,它與 C++ 中的模板和 Java 語言中提出的泛型在語法上只是稍有差別,但在實現方式上卻存在很大差別。

生成最新的泛型類
利用目前的 C#,程序員可以通過在基本對象類型的實例中存儲數據來創建有限形式的真正泛型。由於在 C# 中每個對象都是從基本對象類型繼承的,再加上統一 .Net 類型系統的裝箱和取消裝箱功能,程序員可以將引用類型和值類型存儲到對象類型的變量中。但是,對於引用類型、值類型與基本對象類型之間的轉換,還有一些性能缺陷。

為了說明這一點,以下代碼示例創建了一個簡單的 Stack 類型,其中包含兩個操作“Push”和“Pop”。Stack 類將其數據存儲在對象類型的數組中,Push 和 Pop 方法使用基本對象類型來接受和返回數據:

public class Stack
{
   private object[] items = new object[100];

   public void Push(object data)
   {
      ...
   }

   public object Pop()
   {
      ...
   }
}
然後,就可以將自定義類型(例如 Customer 類型)壓入堆棧。但是,如果程序需要檢索數據,則需要將 Pop 方法的結果(基本對象類型)顯式轉換成 Customer 類型。

Stack s = new Stack();
s.Push(new Customer());
Customer c = (Customer) s.Pop();
如果將一個值類型(例如一個整數)傳遞給 Push 方法,運行時會自動將其轉換為引用類型(該過程稱作裝箱),然後將其存儲在內部數據結構中。與此類似,如果程序要從堆棧中檢索一個值類型(例如一個整數),則需要將從 Pop 方法獲取的對象類型顯式轉換成值類型,該過程稱作取消裝箱:

Stack s = new Stack();
s.Push(3);
int i = (int) s.Pop();
值類型和引用類型之間的裝箱和取消裝箱操作非常繁重。

而且,在當前的實現中,無法限制堆棧中放置的數據類型。實際上,可以先創建堆棧,然後將 Customer 類型壓入堆棧。然後,可使用同一堆棧並嘗試將數據彈出,接著將其轉換為其他類型,如下例所示:

Stack s = new Stack();
s.Push(new Customer());

Employee e = (Employee) s.Pop();
盡管上一個代碼示例錯誤地使用了要實現的單個類型 Stack 類,應視為錯誤,但它實際上卻是合法代碼,對它進行編譯時不會出現問題。但在運行時,該程序會由於無效轉換操作而失敗。

創建和使用泛型
使用 C# 中的泛型可以根據它們所用的類型創建專供編譯器使用的高效數據結構。創建這些所謂的參數化類型後,其內部算法保持不變,但其內部數據的類型可以隨著最終用戶的設置而改變。

為了幫助開發人員節省學習該語言的時間,C# 中泛型的聲明方法與 C++ 中的大致相同。程序員可以按通常的方法創建類和結構,並使用尖括號標記(< 和 >)指定類型參數。使用類時,必須用該類的用戶提供的實際類型替換每個參數。

下例將創建一個 Stack 類,在此類聲明後的尖括號中指定並聲明一個名為 ItemType 的類型參數。泛型 Stack 類的實例將接受為其創建的類型並在本地存儲該類型的數據,而不是在創建的類型與基本對象類型之間進行轉換。類型參數 ItemType 充當代理,直到在實例化過程中指定了類型並將其用作內部項數組的類型(即 Push 方法的參數類型和 Pop 方法的返回類型):

public class Stack<ItemType>
{
   private ItemType[] items;

   public void Push(ItemType data)
   {
      ...
   }

   public ItemType Pop()
   {
      ...
   }
}
當程序按照以下示例使用 Stack 類時,您可以指定泛型類使用的實際類型。本例使用實例化語句中的尖括號標記將原始的整數類型指定為參數,指示 Stack 類使用此類型:

Stack<int> stack = new Stack<int>();
stack.Push(3);
int x = stack.Pop();
執行此操作時,程序將創建 Stack 類的新實例,其中的每個 ItemType 都被提供的整數參數替換。實際上,當程序用整數參數創建 Stack 類的新實例時,在 Stack 類內部本地存儲的項目數組將為整數,而不是對象。程序還消除了與將整數壓入堆棧相關聯的裝箱問題。此外,當程序從堆棧彈出項目時,您無需將其顯式轉換為相應的類型,因為 Stack 類的當前特定實例會將整數本地存儲在其數據結構中。

如果希望程序在 Stack 類中存儲其他類型的項目,則必須創建一個 Stack 類的新實例並將新類型指定為參數。假設有一個簡單的 Customer 類型,希望程序使用 Stack 對象存儲該類型。要實現此操作,只需實例化 Stack 類並將 Customer 對象作為其類型參數,即可輕松重復使用程序代碼:

Stack<Customer> stack = new Stack<Customer>();
stack.Push(new Customer());
Customer c = stack.Pop();
當然,如果程序創建了一個將 Customer 類型作為參數的 Stack 類,則只能在該堆棧中存儲 Customer 類型。實際上,C# 中的泛型具有嚴格的類型,這意味著您不能在該堆棧中存儲整數,如以下示例所示:

Stack<Customer> stack = new Stack<Customer>();
stack.Push(new Customer());
stack.Push(3)  // 編譯時錯誤
Customer c = stack.Pop();      // 不需要類型轉換。
泛型的優點
使用泛型,程序員只需編寫、測試和部署一次代碼,即可對各種不同的數據類型重復使用該代碼。第一個 Stack 示例具備此功能,第二個 Stack 示例允許程序重復使用對其應用程序性能影響不大的代碼。對於值類型,第一個 Stack 示例具有較大的性能問題,而第二個 Stack 示例完全消除了這種問題,因為它去除了裝箱和向下的類型轉換。

而且,編譯時還會對泛型進行檢查。當程序使用提供的類型參數實例化泛型類時,此類型參數只能是程序在類定義中指定的類型。例如,如果程序創建了一個 Customer 對象類型的 Stack,就無法將整數壓入堆棧。通過強制執行這種操作,可以生成更可靠的代碼。

此外,與其他嚴格的類型實現相比,泛型的 C# 實現降低了代碼的膨脹速度。使用泛型創建具有類型的集合,可以在保持操作性能優勢的同時避免創建每個類的特定變體。例如,程序可以創建一個參數化的 Stack 類,而無需創建用於存儲整數的 IntegerStack、用於存儲字符串的 StringStack 以及用於存儲 Customer 類型的 CustomerStack。

這樣可以增加代碼的可讀性。只需創建一個 Stack 類,程序就可以將與某個堆棧相關聯的所有操作封裝在一個使用方便的類中。然後,在創建 Customer 類型的 Stack 時,盡管其中存儲了 Customer 類型,但顯而易見,程序使用的仍然是堆棧數據結構。

多個類型參數
泛型可以使用任意多個參數類型。上面的 Stack 示例中只使用了一種類型。假設您創建了一個存儲值和鍵的簡單 Dictionary 類。在程序中可以通過聲明兩個參數(放在類定義的尖括號中並用逗號分隔)來定義一個泛型版本的 Dictionary 類:

public class Dictionary<KeyType, ValType>
{
   public void Add(KeyType key, ValType val)
   {
      ...
   }

   public ValType this[KeyType key]
   {
      ...
   }
}
使用該 Dictionary 類時,需要在實例化語句的尖括號中提供多個以逗號分隔的參數,並為 Add 函數和索引生成器提供正確類型的參數:

Dictionary<int, Customer> dict = new Dictionary<int, Customer>();
dict.Add(3, new Customer());
Customer c = dict.Get[3];
約束
通常情況下,程序並不僅僅局限於根據給定的類型參數存儲數據,而是經常需要使用類型參數的成員來執行程序泛型中的語句。

為什麼需要約束

假設在 Dictionary 類的 Add 方法中,您需要使用所提供的鍵的 CompareTo 方法比較項目,例如:

public class Dictionary<KeyType, ValType>
{
   public void Add(KeyType key, ValType val)
   {
      ...
      switch(key.CompareTo(x))
      {
      }
      ...
   }
}
遺憾的是,正如預期那樣,類型參數 KeyType 在編譯時是泛型。如果這樣編寫,編譯器假設對類型參數為 KeyType 的 key 實例只能執行適用於基本對象類型(例如 ToString)的操作。結果,由於 CompareTo 方法未定義,編譯器將顯示編譯錯誤。然而,程序可以將 key 變量轉換為包含 CompareTo 方法的對象,例如 IComparable 接口。在以下示例中,程序將 KeyType 參數類型的實例 key 顯式轉換為程序可以編譯的 IComparable 接口:

public class Dictionary<KeyType, ValType>
{
   public void Add(KeyType key, ValType val)
   {
      ...
      switch(((IComparable) key).CompareTo(x))
      {
      }
      ...
   }
}
然而,如果立即實例化 Dictionary 類而且提供的類型參數沒有實現 IComparable 接口,則程序將遇到運行時錯誤,尤其是 InvalidCastException 異常。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved