日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
簡(jiǎn)單介紹CLR泛型及其優(yōu)勢(shì)

泛型是對(duì) CLR 類(lèi)型系統(tǒng)的擴(kuò)展,它允許開(kāi)發(fā)人員定義那些未指定某些細(xì)節(jié)的類(lèi)型。相反,當(dāng)用戶代碼引用該代碼時(shí),就會(huì)指定這些細(xì)節(jié)。引用泛型的代碼填充缺少的細(xì)節(jié),并根據(jù)其特定需求對(duì)類(lèi)型進(jìn)行調(diào)整。泛型的命名反映了該功能的目標(biāo):允許在編寫(xiě)代碼時(shí)不指定可能限制其使用范圍的細(xì)節(jié)。代碼本身就是泛型。稍后,我會(huì)對(duì)它進(jìn)行更詳細(xì)的介紹。

CLR泛型預(yù)覽

正如使用任何新技術(shù)一樣,明白它的好處所在會(huì)有所幫助。那些熟悉 C++ 模板的用戶將會(huì)發(fā)現(xiàn),泛型在托管代碼中具有相似的用途。但是,我不愿意對(duì) CLR 泛型和 C++ 模板進(jìn)行過(guò)多比較,因?yàn)榉盒途哂幸恍╊~外的好處,它不存在以下兩個(gè)常見(jiàn)問(wèn)題:代碼臃腫和開(kāi)發(fā)人員混淆。

CLR 泛型具有一些好處,如編譯時(shí)類(lèi)型安全、二進(jìn)制代碼重用、性能和清晰性。我將簡(jiǎn)要介紹這些好處,您在閱讀本專(zhuān)欄的其余文章時(shí),會(huì)更詳細(xì)地了解它們。例如,假設(shè)有兩個(gè)集合類(lèi):SortedList(Object 引用的集合)和 GenericSortedList< T>(任意類(lèi)型的集合)。

類(lèi)型安全:當(dāng)用戶向 SortedList 類(lèi)型的集合內(nèi)添加 String 時(shí),String 會(huì)隱式強(qiáng)制轉(zhuǎn)換為 Object。同樣,如果從該列表中檢索 String 對(duì)象,則它必須在運(yùn)行時(shí)從 Object 引用強(qiáng)制轉(zhuǎn)換到 String 引用。這會(huì)造成編譯時(shí)缺少類(lèi)型安全,從而使開(kāi)發(fā)人員感到厭煩,并且易于出錯(cuò)。相反,如果使用 GenericSortedList< String>(T 的類(lèi)型被設(shè)置為 String),就會(huì)使所有的添加和查找方法使用 String 引用。這允許在編譯時(shí)(而非運(yùn)行時(shí))指定和檢查元素的類(lèi)型。

二進(jìn)制代碼重用:為了進(jìn)行維護(hù),開(kāi)發(fā)人員可以選擇使用 SortedList ,通過(guò)從它派生 SortedListOfString 來(lái)實(shí)現(xiàn)編譯時(shí)的類(lèi)型安全。此方法有一個(gè)問(wèn)題,那就是必須對(duì)于每個(gè)需要類(lèi)型安全列表的類(lèi)型都編寫(xiě)新代碼,而這會(huì)很快變成非常費(fèi)力的工作。使用 GenericSortedList< T>,需要執(zhí)行的全部操作就是將具有所需元素類(lèi)型的類(lèi)型實(shí)例化為 T。泛型代碼還有一個(gè)附加價(jià)值,那就是它在運(yùn)行時(shí)生成,因此,對(duì)于無(wú)關(guān)元素類(lèi)型的兩個(gè)擴(kuò)展(如 GenericSortedList< String> 和 GenericSortedList< FileStream>)能夠重新使用同一個(gè)實(shí)時(shí) (JIT) 編譯代碼的大部分。CLR 只是處理細(xì)節(jié) — 代碼不再臃腫!

性能:關(guān)鍵在于:如果類(lèi)型檢查在編譯時(shí)間進(jìn)行,而不是在運(yùn)行時(shí)間進(jìn)行,則性能增強(qiáng)。在托管代碼中,引用和值之間的強(qiáng)制轉(zhuǎn)換既會(huì)導(dǎo)致裝箱又會(huì)導(dǎo)致取消裝箱,而且避免這樣的強(qiáng)制轉(zhuǎn)換可能會(huì)對(duì)性能產(chǎn)生同樣的負(fù)面影響。最近針對(duì)一個(gè)由一百萬(wàn)個(gè)整數(shù)組成的數(shù)組進(jìn)行了快速排序法基準(zhǔn)測(cè)試,結(jié)果表明泛型方法比非泛型方法快三倍。這是由于完全避免了對(duì)這些值進(jìn)行裝箱。如果針對(duì)由字符串引用組成的數(shù)組進(jìn)行同樣的排序,則由于無(wú)需在運(yùn)行時(shí)執(zhí)行類(lèi)型檢查,因此使用泛型方法后性能提高了 20%。

清晰性:泛型的清晰性體現(xiàn)在許多方面。約束是泛型的一個(gè)功能,它們會(huì)禁止對(duì)泛型代碼進(jìn)行不兼容的擴(kuò)展;使用泛型,您將不再面臨那些困擾 C++ 模板用戶的含混不清的編譯器錯(cuò)誤。在 GenericSortedList< T> 示例中,集合類(lèi)將有一個(gè)約束,該約束使集合類(lèi)只處理可進(jìn)行比較并依此進(jìn)行排序的 T 類(lèi)型。同樣,通??梢允褂妹麨轭?lèi)型推理的功能來(lái)調(diào)用泛型方法,而無(wú)需使用任何特殊語(yǔ)法。當(dāng)然,編譯時(shí)類(lèi)型安全可以使應(yīng)用程序代碼更加清晰。 我將在本文中詳細(xì)介紹約束、類(lèi)型推理和類(lèi)型安全。

#p#

一個(gè)簡(jiǎn)單的CLR泛型示例

Whidbey CLR 版本將通過(guò)類(lèi)庫(kù)中的一套泛型集合類(lèi)來(lái)提供這些現(xiàn)成的好處。但是,可通過(guò)為應(yīng)用程序定義其自己的泛型代碼,使其進(jìn)一步受益于泛型。為了解釋這是如何完成的,我將首先修改一個(gè)簡(jiǎn)單的鏈接列表節(jié)點(diǎn)類(lèi),使其成為泛型類(lèi)類(lèi)型。

以下代碼中的 Node 類(lèi)只是包括一些基本內(nèi)容。它有兩個(gè)字段:m_data(引用節(jié)點(diǎn)的數(shù)據(jù))和 m_data(引用鏈接列表中的下一項(xiàng))。這兩個(gè)字段都是由構(gòu)造函數(shù)方法設(shè)置的。確實(shí)只有兩個(gè)其他點(diǎn)綴性功能,第一個(gè)功能是通過(guò)名為 Data 和 Next 的只讀屬性訪問(wèn) m_data 和 m_next 字段。第二個(gè)功能是對(duì) System.Object 的 ToString 虛擬方法進(jìn)行重寫(xiě)。

 
 
 
  1. using System;  
  2.  
  3. // Definition of a node type for creating a linked list  
  4. class Node {  
  5.    Object  m_data;  
  6.    Node    m_next;  
  7.  
  8.    public Node(Object data, Node next) {  
  9.       m_data = data;  
  10.       m_next = next;  
  11.    }  
  12.  
  13.    // Access the data for the node  
  14.    public Object Data {  
  15.       get { return m_data; }   
  16.    }  
  17.  
  18.    // Access the next node  
  19.    public Node Next {  
  20.       get { return m_next; }   
  21.    }  
  22.  
  23.    // Get a string representation of the node  
  24.    public override String ToString() {  
  25.       return m_data.ToString();  
  26.    }              
  27. }  
  28.  
  29. // Code that uses the node type  
  30. class App {  
  31.    public static void Main() {  
  32.  
  33.       // Create a linked list of integers  
  34.       Node head = new Node(5, null);  
  35.       head = new Node(10, head);  
  36.       head = new Node(15, head);  
  37.  
  38.       // Sum-up integers by traversing linked list  
  39.       Int32 sum = 0;  
  40.       for (Node current = head; current != null;  
  41.          current = current.Next) {  
  42.          sum += (Int32) current.Data;  
  43.       }        
  44.  
  45.       // Output sum  
  46.       Console.WriteLine("Sum of nodes = {0}", sum);        
  47.    }  
  48. }  

上面還顯示了使用 Node 類(lèi)的代碼。該引用代碼會(huì)受到某些限制。問(wèn)題在于,為了能在許多上下文中使用,其數(shù)據(jù)必須為最基本的類(lèi)型,即 System.Object。這意味著使用 Node 時(shí),就會(huì)失去任何形式的編譯時(shí)類(lèi)型安全。使用 Object 意味著算法或數(shù)據(jù)結(jié)構(gòu)中的“任意類(lèi)型”會(huì)強(qiáng)迫所使用的代碼在 Object 引用和實(shí)際數(shù)據(jù)類(lèi)型之間進(jìn)行強(qiáng)制轉(zhuǎn)換。應(yīng)用程序中的任何類(lèi)型不匹配錯(cuò)誤只有在運(yùn)行之后才被捕獲。如果在運(yùn)行時(shí)嘗試進(jìn)行強(qiáng)制轉(zhuǎn)換,這些錯(cuò)誤會(huì)采用 InvalidCastException 形式。

此外,如果要向 Object 引用賦予任何基元值(如 Int32),則需要對(duì)實(shí)例進(jìn)行裝箱。裝箱涉及到內(nèi)存分配和內(nèi)存復(fù)制,以及最后對(duì)已裝箱值進(jìn)行的垃圾回收。最后,正如可在 圖 1 中看到的那樣,從 Object 引用強(qiáng)制轉(zhuǎn)換為值類(lèi)型(如 Int32)會(huì)導(dǎo)致取消裝箱(也包括類(lèi)型檢查)。 由于裝箱和取消裝箱會(huì)損害該算法的整體性能,因此您會(huì)明白為什么用 Object 就意味著“任何類(lèi)型”都具有一定的缺點(diǎn)。

使用泛型重寫(xiě) Node 是解決這些問(wèn)題的完美方法。讓我們看一下下面的代碼,您將發(fā)現(xiàn) Node 類(lèi)型被重寫(xiě)為 Node< T> 類(lèi)型。具有泛型行為的類(lèi)型(如 Node< T>)是參數(shù)化類(lèi)型,并且可被稱(chēng)作 Parameterized Node、Node of T 或泛型Node。稍后我將介紹這個(gè)新的 C# 語(yǔ)法;讓我們首先深入研究一下 Node< T> 與 Node 有何不同。

 
 
 
  1. class Node  {  
  2.    T        m_data;  
  3.    Node   m_next;  
  4.  
  5.    public Node(T data, Node  next) {  
  6.       m_data = data;  
  7.       m_next = next;  
  8.    }  
  9.  
  10.    // Access the data for the node  
  11.    public T Data {  
  12.       get { return m_data; }   
  13.       set { m_data = value; }  
  14.    }  
  15.  
  16.    // Access the next node  
  17.    public Node  Next {  
  18.       get { return m_next; }   
  19.       set { m_next = value; }  
  20.    }  
  21.  
  22.    // Get a string representation of the node  
  23.    public override String ToString() {  
  24.       return m_data.ToString();  
  25.    }              
  26. }  

Node< T> 類(lèi)型與 Node 類(lèi)型在功能和結(jié)構(gòu)上相似。二者均支持為任何給定類(lèi)型的數(shù)據(jù)構(gòu)建鏈接列表。但是,Node 使用 System.Object 來(lái)表示“任意類(lèi)型”,而 Node< T> 不指定該類(lèi)型。相反,Node< T> 使用名為 T 且作為類(lèi)型占位符的類(lèi)型參數(shù)。當(dāng)使用者代碼使用 Node< T> 時(shí),名為 T 的類(lèi)型參數(shù)最終由 Node< T> 的參數(shù)來(lái)指定。

 
 
 
  1. class App {  
  2.    public static void Main() {  
  3.  
  4.       // Create a linked list of integers  
  5.       Node  head =  new Node (5,  null);  
  6.       head = new Node (10, head);  
  7.       head = new Node (15, head);  
  8.  
  9.       // Sum up integers by traversing linked list  
  10.       Int32 sum = 0;  
  11.       for (Node  current = head; current !=  null;   
  12.          current = current.Next) {  
  13.          sum += current.Data;  
  14.       }        
  15.  
  16.       // Output sum  
  17.       Console.WriteLine("Sum of nodes = {0}", sum.ToString());        
  18.    }  
  19. }  

以上中的代碼使用了具有 32 位帶符號(hào)整數(shù)的 Node< T>,這是通過(guò)構(gòu)造類(lèi)似類(lèi)型名稱(chēng):Node< Int32> 來(lái)實(shí)現(xiàn)的。在本例中,Int32 是類(lèi)型參數(shù) T 的類(lèi)型變量。(順便說(shuō)一句,C# 還將接受Node< int>,以便將 T 指示為 Int32。) 如果該代碼需要某種其他類(lèi)型(如 String 引用)的鏈接列表,則這可通過(guò)將它指定為 T 的類(lèi)型變量來(lái)完成,例如:Node< String>。

Node< T> 的好處在于:它的算法行為可被明確定義,而它所操作的數(shù)據(jù)類(lèi)型仍保持未指定狀態(tài)。因此,Node< T> 類(lèi)型在工作方式上是具體的;而泛型在所處理的內(nèi)容方面又是具體的??傊?,諸如鏈接列表應(yīng)當(dāng)擁有的數(shù)據(jù)類(lèi)型等細(xì)節(jié)最好留給使用 Node< T> 的代碼來(lái)指定。

在討論泛型時(shí),最好先明確兩種角色:定義代碼和引用代碼。定義代碼包括既聲明泛型代碼存在又定義類(lèi)型成員(如方法和字段)的代碼。 圖 2 中顯示的是類(lèi)型 Node< T> 的定義代碼。引用代碼是用戶代碼,它使用預(yù)定義的泛型代碼,并且該代碼還可以內(nèi)置到另一個(gè)程序集中。 圖 3 是 Node< T> 的引用代碼示例。

考慮定義代碼和引用代碼非常有用,原因在于這兩種角色都在實(shí)際的可使用泛型代碼構(gòu)造中起著一定的作用。 圖 3 中的引用代碼使用 Node< T> 來(lái)構(gòu)造一個(gè)名為 Node< T> 的新類(lèi)型。Node< Int32> 是一個(gè)截然不同的類(lèi)型,它由以下兩個(gè)關(guān)鍵成分構(gòu)建而成:Node< T>(由定義代碼創(chuàng)建),參數(shù) T 的類(lèi)型變量 Int32(由引用代碼指定)。只有使用這兩個(gè)成分才能使泛型代碼變得完整。

請(qǐng)注意,從面向?qū)ο蟮呐缮嵌瓤?,泛型?lèi)型(如 Node< T>)以及從泛型類(lèi)型構(gòu)造的類(lèi)型(如 Node< Int32> 或 Node< String>)并不是相關(guān)類(lèi)型。類(lèi)型 Node< Int32>、Node< String> 和 Node< T> 類(lèi)型是同輩,它們都是從 System.Object 直接派生而來(lái)。

#p#

C# Generic 語(yǔ)法

CLR 支持多種編程語(yǔ)言,因此,CLR 泛型將有多種語(yǔ)法。但是,無(wú)論采用哪種語(yǔ)法,用一種面向 CLR 的語(yǔ)言編寫(xiě)的泛型代碼將可以由其他面向 CLR 的語(yǔ)言編寫(xiě)的程序使用。我將在本文中介紹 C# 語(yǔ)法,其原因是,在編寫(xiě)本文時(shí),在三種較大的托管語(yǔ)言中,泛型的 C# 語(yǔ)法相當(dāng)穩(wěn)定。 但是,沒(méi)有必要在 Visual Basic?.NET 和 Managed C++ 的 Whidbey 版本中支持泛型。

下表顯示了泛型定義代碼和泛型引用代碼的基本 C# 語(yǔ)法。二者的語(yǔ)法區(qū)別反映了泛型代碼所涉及的雙方的不同職責(zé)。

Defining Code Referencing Code
class Node { T m_data; Node m_next; } 
class Node8Bit : Node { ...} 
struct Pair { T m_element1; U m_element2; } 
Pair pair; pair.m_element1 = 255; pair.m_element2 = "Hi"; 
interface IComparable { Int32 CompareTo(T other); } 
class MyType : IComparable { public Int32 CompareTo(MyType other) { ... } } 
void Swap
     
      (
      ref T item1, ref T item2) { T temp = item1; item1 = item2; item2 = temp; } 
     
Decimal d1 = 0, d2 = 2;
Swap(ref d1, ref d2); 
delegate void EnumerateItem
      
       (T item); 
      
...   EnumerateItem callback = 
     new EnumerateItem(CallMe); } void CallMe(Int32 num) { ... } 

目前的計(jì)劃是讓 CLR(從而讓 C#)支持泛型類(lèi)、結(jié)構(gòu)、方法、接口和委托。 上表的左側(cè)顯示了每種定義代碼情況的 C# 語(yǔ)法示例。.請(qǐng)注意,尖括號(hào)表示類(lèi)型參數(shù)列表。尖括號(hào)緊跟在泛型類(lèi)型或成員的名稱(chēng)后面。同樣,在類(lèi)型參數(shù)列表中有一個(gè)或多個(gè)類(lèi)型參數(shù)。參數(shù)還出現(xiàn)在泛型代碼的整個(gè)定義中,用來(lái)替代特定的 CLR 類(lèi)型或作為類(lèi)型構(gòu)造函數(shù)的參數(shù)。 圖 4 的右側(cè)顯示了與之相匹配的引用代碼情況的 C# 語(yǔ)法示例。請(qǐng)注意,在此處,類(lèi)型變量括在尖括號(hào)中;泛型標(biāo)識(shí)符和括號(hào)構(gòu)成一個(gè)截然不同的新標(biāo)識(shí)符。另外還要注意,類(lèi)型變量指定在從泛型構(gòu)造類(lèi)型或方法時(shí)所使用的類(lèi)型。

讓我們花一點(diǎn)時(shí)間來(lái)定義代碼語(yǔ)法。當(dāng)編譯器遇到一個(gè)由尖括號(hào)分開(kāi)的類(lèi)型參數(shù)列表時(shí),它可識(shí)別出您在定義泛型類(lèi)型或方法。泛型定義中的尖括號(hào)緊跟在所定義的類(lèi)型或方法的名稱(chēng)后面。

類(lèi)型-參數(shù)列表指出要在泛型代碼定義中保持未指定狀態(tài)的一個(gè)或多個(gè)類(lèi)型。類(lèi)型參數(shù)的名稱(chēng)可以是 C# 中任何有效的標(biāo)識(shí)符,它們可用逗號(hào)隔開(kāi)。對(duì)于“定義代碼”部分中的類(lèi)型參數(shù),需要注意下面一些事項(xiàng):

在每個(gè)代碼示例中,可以看到在整個(gè)定義中(通常將出現(xiàn)類(lèi)型名稱(chēng)的位置)均使用了類(lèi)型參數(shù) T 或 U。

在 IComparable< T> 接口示例中,可以看到同時(shí)使用類(lèi)型參數(shù) T 和常規(guī)類(lèi)型 Int32。在泛型代碼的定義中,既可以使用未指定的類(lèi)型(通過(guò)類(lèi)型參數(shù))又可以使用指定的類(lèi)型(使用 CLR 類(lèi)型名稱(chēng))。

在 Node< T> 示例中,可以看到,類(lèi)型參數(shù) T 可以像在 m_data 的定義中一樣獨(dú)立使用,還可以像在 m_next 中一樣用作另一個(gè)類(lèi)型構(gòu)造的一部分。用作另一個(gè)泛型類(lèi)型定義的變量的類(lèi)型參數(shù)(如 Node< T>),稱(chēng)作開(kāi)放式泛型類(lèi)型。用作類(lèi)型參數(shù)的具體類(lèi)型(如 Node< System.Byte>),稱(chēng)作封閉式泛型類(lèi)型。

與任何泛型方法一樣, 表格中顯示的示例泛型方法 Swap< T> 可以是泛型或非泛型類(lèi)型的一部分,也可以是實(shí)例、虛擬或靜態(tài)方法。

在本文中,我對(duì)于類(lèi)型參數(shù)使用的是單字符名稱(chēng)(如 T 和 U),這主要是為了使情況更簡(jiǎn)單。但是,您會(huì)發(fā)現(xiàn)也可以使用描述性名稱(chēng)。例如,在產(chǎn)品代碼中,Node< T> 類(lèi)型可被等效地定義為 Node< ItemType> 或 Node< dataType>。

在撰寫(xiě)本文時(shí),Microsoft 已經(jīng)使庫(kù)代碼中的單字符類(lèi)型參數(shù)名稱(chēng)標(biāo)準(zhǔn)化,以有助于區(qū)分這些名稱(chēng)與用于普通類(lèi)型的名稱(chēng)。我個(gè)人比較喜歡在產(chǎn)品代碼中使用 camelCasing 類(lèi)型參數(shù),因?yàn)檫@可將它們與代碼中的簡(jiǎn)單類(lèi)型名稱(chēng)相區(qū)分,而同時(shí)又具有一定的描述性。

在泛型引用代碼中,未指定的類(lèi)型會(huì)變成指定的類(lèi)型。如果引用代碼實(shí)際使用泛型代碼,則這是十分必要的。如果您查看 圖 4 中“Referencing Code”部分中的示例,就會(huì)發(fā)現(xiàn)在所有情況中,新類(lèi)型或方法都是通過(guò)將 CLR 類(lèi)型指定為泛型的類(lèi)型變量,從一個(gè)泛型構(gòu)造的。在泛型語(yǔ)法中,諸如 Node< Byte> 和 Pair< Byte,String> 之類(lèi)的代碼表示從泛型類(lèi)型定義構(gòu)造的新類(lèi)型的類(lèi)型名稱(chēng)。

在深入介紹該技術(shù)本身之前,我將再介紹一個(gè)語(yǔ)法細(xì)節(jié)。當(dāng)代碼調(diào)用泛型方法(如 Swap< T> 方法)時(shí),完全限定的調(diào)用語(yǔ)法包括任何類(lèi)型變量。但是,有時(shí)可以選擇將類(lèi)型變量從調(diào)用語(yǔ)法中排除,如下面的兩行代碼所示:

 
 
 
  1. Decimal d1 = 0, d2 = 2;  
  2. Swap(ref d1, ref d2);  

這個(gè)簡(jiǎn)化的調(diào)用語(yǔ)法依賴(lài)一個(gè)名為類(lèi)型推理的 C# 編譯器功能,在該功能中,編譯器使用傳遞給方法的參數(shù)類(lèi)型來(lái)推導(dǎo)類(lèi)型變量。在本例中,編譯器從 d1 和 d2 的數(shù)據(jù)類(lèi)型來(lái)推導(dǎo),類(lèi)型參數(shù) T 的類(lèi)型變量應(yīng)當(dāng)為 System.Decimal。如果存在多義性,類(lèi)型推理對(duì)于調(diào)用方不工作,并且 C# 編譯器將會(huì)產(chǎn)生一個(gè)錯(cuò)誤,建議您使用包含尖括號(hào)和類(lèi)型變量的完整調(diào)用語(yǔ)法。

#p#

CLR泛型:間接

我的一個(gè)好朋友喜歡指出,大多數(shù)完美的編程解決方案都是圍繞添加另一間接層次而設(shè)計(jì)的。指針和引用允許單個(gè)函數(shù)影響一個(gè)數(shù)據(jù)結(jié)構(gòu)的多個(gè)實(shí)例。虛擬函數(shù)允許單個(gè)調(diào)用站點(diǎn)將調(diào)用傳送到一組相似的方法 — 其中一些方法可在以后定義。這兩個(gè)間接示例非常常見(jiàn),以至于程序員通常注意不到間接本身。

間接的主要目的是為了提高代碼的靈活性。泛型是一種間接形式,在這種形式中,定義不會(huì)產(chǎn)生可直接使用的代碼。相反,在定義泛型代碼中,會(huì)創(chuàng)建一個(gè)“代碼工廠”。隨后,引用代碼使用該工廠代碼來(lái)構(gòu)造可直接使用的代碼。

讓我們首先從泛型方法來(lái)了解這個(gè)設(shè)計(jì)思路。 圖 5 中的代碼定義并引用了一個(gè)名為 CompareHashCodes< T> 的泛型方法。定義代碼創(chuàng)建了一個(gè)名為 CompareHashCodes< T> 的泛型方法,但是 圖 5 中顯示的代碼都沒(méi)有直接調(diào)用 CompareHashCodes< T>。相反,在 Main 中,引用代碼使用 CompareHashCodes< T> 來(lái)構(gòu)造兩種不同的方法:CompareHashCodes< Int32> 和 CompareHashCodes< String>。這些構(gòu)造方法是 CompareHashCodes< T> 的實(shí)例,它們是由引用代碼來(lái)調(diào)用的。

通常會(huì)在某個(gè)方法的定義中直接定義該方法所執(zhí)行的操作。與之相反,在泛型方法的定義中,會(huì)定義它的構(gòu)造方法實(shí)例將執(zhí)行的操作。除了充當(dāng)如何構(gòu)造特定實(shí)例的模型以外,泛型方法本身不執(zhí)行任何操作。CompareHashCodes< T> 是一種泛型方法,通過(guò)它可以構(gòu)造對(duì)哈希代碼進(jìn)行比較的方法實(shí)例。 構(gòu)造實(shí)例(如 CompareHashCodes< Int32>)執(zhí)行實(shí)際工作;它對(duì)整數(shù)的哈希代碼進(jìn)行比較。相反,CompareHashCodes< T> 是一個(gè)從可調(diào)用中刪除的間接層。

泛型類(lèi)型類(lèi)似于從與其相對(duì)應(yīng)的簡(jiǎn)單副本中刪除的一個(gè)間接層。系統(tǒng)使用簡(jiǎn)單的類(lèi)型定義(如類(lèi)或結(jié)構(gòu))來(lái)創(chuàng)建內(nèi)存中的對(duì)象。例如,類(lèi)庫(kù)中的 System.Collection.Stack 類(lèi)型用于在內(nèi)存中創(chuàng)建堆棧對(duì)象。在某種意義上,可以將 C# 中的新關(guān)鍵字或中間語(yǔ)言代碼中的 newobj 指令視為一個(gè)對(duì)象工廠,該對(duì)象工廠在創(chuàng)建對(duì)象實(shí)例時(shí),將托管類(lèi)型用作每個(gè)對(duì)象的藍(lán)圖。

另一方面,泛型類(lèi)型用于實(shí)例化封閉式類(lèi)型,而不是對(duì)象實(shí)例。隨后,可以使用從泛型類(lèi)型構(gòu)造的類(lèi)型來(lái)創(chuàng)建對(duì)象。讓我們回顧一下在 圖 2 中定義的 Node< T> 類(lèi)型以及如 圖 3所示的它的引用代碼。

托管應(yīng)用程序永遠(yuǎn)不能創(chuàng)建 Node< T> 類(lèi)型的對(duì)象,即使它是托管類(lèi)型時(shí)也是如此。這是由于 Node< T> 缺乏足夠的定義,因此無(wú)法被實(shí)例化為內(nèi)存中的對(duì)象。但是,在執(zhí)行應(yīng)用程序的過(guò)程中,Node< T> 可用于實(shí)例化另一個(gè)類(lèi)型。

Node< T> 是一個(gè)開(kāi)放式泛型類(lèi)型,并且只用于創(chuàng)建其他構(gòu)造類(lèi)型。如果使用 Node< T> 創(chuàng)建的構(gòu)造類(lèi)型是封閉式類(lèi)型(如 Node< Int32>),則它可用于創(chuàng)建對(duì)象。 圖 3 中的引用代碼使用 Node< Int32> 的方式與使用簡(jiǎn)單類(lèi)型時(shí)大體相同。它創(chuàng)建 Node< Int32> 類(lèi)型的對(duì)象,在這些對(duì)象上調(diào)用方法,等等。

泛型類(lèi)型額外提供一個(gè)間接層,此功能非常強(qiáng)大。采用泛型類(lèi)型的引用代碼會(huì)產(chǎn)生定制的托管類(lèi)型。在腦海中將泛型代碼想象為從其簡(jiǎn)單副本中刪除的一個(gè)間接層,這有助于憑直覺(jué)獲知 CLR 中泛型的許多行為、規(guī)則和用法。

CLR泛型小結(jié)

本文介紹了泛型類(lèi)型的好處 — 如何使用它們改善類(lèi)型安全、代碼重用和性能。本文還講述了 C# 中的語(yǔ)法以及泛型如何導(dǎo)致另一層間接,從而提高靈活性。


網(wǎng)站標(biāo)題:簡(jiǎn)單介紹CLR泛型及其優(yōu)勢(shì)
網(wǎng)頁(yè)路徑:http://www.dlmjj.cn/article/djdedph.html