Viusal Basic程序員的.NET泛型編程
一、引言 在《The C++ Programming Language》一書中,Bjarne Stroustrop討論了模板方法在C語言中的偽實現-通過使用預處理和宏來模擬。Stroustrop創建了這種靈活運用C語言的模板和宏的能力,它使得模板成為用C語言創建類(現在的C++)的相當成熟的一部分。另
一、引言
在《The
C++ Programming Language》一書中,Bjarne Stroustrop討論了
模板方法在C語言中的偽實現-通過使用預處理和宏來模擬。Stroustrop創建了這種靈活運用C語言的
模板和宏的能力,它使得模板成為用C語言創建類(現在的
C++)的相當成熟的一部分。另外的優點是,模板是由編譯器進行類型檢查的,而不是簡單地通過預處理器進行文本替換。
.NET 2.0支持稱為泛型的模板。其基本概念是相同的:用一個或多個方法來定義一個方法或類,并指定數據類型作為一個可替代的元素。習慣情況下,都使用大寫字符T。最后,當你使用該方法或類時,指明一種類型給泛型T,然后編譯器將基于那種類型使用新的信息來生成一個新的且唯一的方法或類。這種新的元素變成了一個完整的獨特的代碼塊,這完全得益于編譯器的處理能力。
本文將分析隨著.NET 2.0一起發布的泛型方法和類的定義以及泛型類的使用問題。
二、定義泛型方法
.NET 2.0的泛型化能力可以定義到單一方法這樣的粒度。解決的方法是把數據類型與算法獨立開來并參數化該數據類型。每一次用不同的數據類型對該方法的參照引用都產生一個不同的方法。泛型方法還支持約束和重載。一個泛型方法約束是一個新出現的語言特征,它可以把一個類型約束添加到泛型類型上去;這樣以來就限制了泛型參數的數據類型。因而,可以根據泛型參數的存在情況,對方法進行重載。(接下來的幾個例子將分析重載的泛型和非泛型方法。)
泛型的典型用法是把數據類型與通用算法分離開來,一個正規的例子就是把排序算法轉化成泛型排序算法。一個非常直接的例子是參數化一個Swap方法。列表1向你展示怎樣定義一個泛型Swap方法-該方法交換兩種任何類型的參數。它包含一個表明怎樣調用泛型方法的控制臺應用程序:
列表1:怎樣調用泛型方法
clearcase/" target="_blank" >cccccc" width="90%" align="center" bgcolor="#e3e3e3" border="1">
Module Module1
Sub Main()
Dim I As Integer = 5
Dim J As Integer = 7
Swap(Of Integer)(I, J)
Console.WriteLine("I = " & I)
Console.WriteLine("J = " & J)
Dim S As String = "Paul"
Dim R As String = "Lori"
Swap(Of String)(S, R)
Console.WriteLine("S = " & S)
Console.WriteLine("R = " & R)
Console.ReadLine()
End Sub
Public Sub Swap(Of T)(ByRef a As T, ByRef b As T)
Dim temp As T
temp = a
a = b
b = temp
End Sub
End Module |
注意:在這個例子中,你也能把一個對象數據類型使用于該Swap方法,因為所有的.NET類型共享一個通用的類型。
需要定義一個泛型方法的新的元素有圓括號,Of關鍵字以及一個描述泛型類型的參數,在方法名Swap的后面的字符(Of T)正是如此。之后,每當使用該泛型類型,都要使用參數化參數(在本例中是T)。
Swap是一個泛型方法,它有兩個可替換的參數和一個可替換的局部變量。例如,Swap(Of Integer)有效地實現了一個有兩個整數參數和一個定義為整數的臨時變量的Swap方法。
1. 添加一個泛型方法約束
假定你想約束列表1中Swap方法中的類型成為非null的結構類型。你可以添加一個約束到Swap上去以指明Swap只可用于值類型(結構)。列表2顯示的Swap方法被約束到結構(或值類型)上。最終結果,在列表1中的Swap(Of String)無法運行:
列表2:帶有約束的Swap方法把Swap方法限制到值類型:
Public Sub Swap(Of T As Structure)(ByRef a As T, ByRef b As T)
Dim temp As T
temp = a
a = b
b = temp
End Sub |
參數化類型可以被限制到結構、類、基類、接口以及有缺省構造器(如沒有參數的Sub New)的類型。列表2中的加粗的As謂詞展示了怎樣約束參數化的類型。
泛型支持定義多個參數化類型,而每個參數化類型可以沒有或者有多個約束。
2. 重載泛型方法
你可以基于一些參數對方法進行重載,但是沒有返回類型,而且方法也能夠被通過參數化類型所重載。例如,下面所有這些形式都可以存在于同一個范圍之內:
Sub Foo
Sub Foo(ByVal s As String)
Sub Foo(Of T)( ByVal arg As T)
Sub Foo(Of T, U)(ByVal arg1 As T, ByVal arg2 as U) |
三、定義一個泛型類
泛型類與普通類一樣定義在相同的實例中,只有一個區別。當你有一些數據和多于一個方法并且其間有關密切的關系時,你可以定義一個普通類。當方法和數據工作在一個密切的單元中并且該數據可以被進一步抽象,以至相同的代碼可以支持許多數據類型時,你最好定義一個泛型類。例如,隊列、列表和堆棧并不在乎它們存儲的東西,而僅在乎怎樣存儲這些東西。如果你使用一個其中存儲有對象的隊列、堆?;蛄斜?,那么你不得不在你的代碼的很多地方進行繁瑣的類型轉化。如果你使用一個泛型隊列、堆?;蛄斜?那么類型轉化只是發生在該類內部。這就是說,繁瑣的類型轉化場所集中于該類的一個內部點上,而該類的用戶可以依賴編譯器來進行類型檢查,并不要求用戶執行if條件檢查和類型變換。
定義一個泛型類就象定義多個泛型方法,只是多了一點:(Of T)構造也可以用于類的頭部。為了說明問題,假定你已定義了一個派生于System.Collections.CollectionBase的泛型的強類型集合(見列表3)。那么現在,你可以把這個類使用于任何數據類型,就好象你已針對所有類型定義了一個定制的類型化的集合:
列表3:一個泛型的強類型集合
Module Module1
Sub Main()
Dim BrokenBones As TypedCollection(Of OrthoInjury) = New TypedCollection(Of OrthoInjury)
BrokenBones.Add(New OrthoInjury(True,"Broken Right Clavicle", "Vicodin; Heals n 8 to 12 weeks"))
BrokenBones.Add(New OrthoInjury(True, "Fractured Posterior Rib #5", "Heals in 6 to 8 weeks"))
BrokenBones.Add(New OrthoInjury(True, "Fractured Posterior Rib #1", "Heals in 6 to 8 weeks"))
Dim injury As OrthoInjury
For Each injury In BrokenBones
Console.WriteLine("Description: " & injury.Description)
Next
Console.ReadLine()
End Sub
End Module
Public Class TypedCollection(Of T)
Inherits System.Collections.CollectionBase
Default Public Property Item(ByVal Index As Integer) As T
Get
Return CType(List(Index), T)
End Get
Set(ByVal value As T)
List(Index) = value
End Set
End Property
Public Function Add(ByVal value As T) As Integer
Return List.Add(value)
End Function
End Class
Public Class OrthoInjury
Private FHasXray As Boolean
Private FDescription As String
Private FPrognosis As String
Public Sub New(ByVal HasXray As Boolean, ByVal Description As String, ByVal Prognosis As String)
FHasXray = HasXray
FDescription = Description
FPrognosis = Prognosis
End Sub
Public Property HasXray() As Boolean
Get
Return FHasXray
End Get
Set(ByVal value As Boolean)
FHasXray = value
End Set
End Property
Public Property Description() As String
Get
Return FDescription
End Get
Set(ByVal value As String)
FDescription = value
End Set
End Property
Public Property Prognosis() As String
Get
Return FPrognosis
End Get
Set(ByVal value As String)
FPrognosis = value
End Set
End Property
End Class |
如果你讀過以前關于類型化的集合的文章,那么你會看到類型化的集合泛型(列表3中的粗體部分)基本上是一種數據類型被參數化的強類型的集合。
四、使用預定義的泛型類
幸好,你不需要從頭開始定義泛型類。System.Collections.Generics命名空間已定義好了許多典型的數據結構用作泛型,例如List,Queue和Stack。你僅需要簡單地導入該命名空間并聲明一個你需要的類型的實例即可。例如,下列代碼充分地實現用.NET 2.0泛型List類型化的集合來替換你的定制的類型化的集合:
Dim BrokenBones As System.Collections.Generic.List(Of OrthoInjury) = _
New System.Collections.Generic.List(Of OrthoInjury) |
作為一個一般規則,如果你想要存儲多于一個類型(異類類型),可以使用更舊的風格類,如Queue和Stack。如果你只想使用一種類型(同類類型),可以使用在System.Collections.Generic命名空間中的新的泛型類。通常情況下,你應使用新的泛型類。
五、選擇所學
能夠把傳統的復雜的如C++這樣的語言與傳統的簡單的如
VB這樣的語言隔離開來的東西越來越少了。乍看起來,這種事實有點令人心灰意冷,因為這就意味著如今的VB越發難學了-就象C++一樣。不過事實上,任何一種語言(包括VB)的核心往往是非常相似的;而即使象C++這樣的語言,你也總可以選擇學習如泛型這樣更高級的概念,如果你需要它們的話??傊?,你可以選擇任何你想學的東西。
還應記住,你總是可以選擇學習任何
編程相關的高級概念-開始作為一個使用者-使用其中的內容,例如泛型List;然后作為一個創建者,學習怎樣創建你自己的東西??偠灾?,想短時間內學精每一件技術可能無法實現,而且也完全沒有必要。
原文轉自:http://www.anti-gravitydesign.com
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97
|