向Visual Basic程序員介紹泛型(二)
2024-07-21 02:21:07
供稿:網(wǎng)友
 
(接上篇)
正如你所見(jiàn),泛型使用起來(lái)很簡(jiǎn)單。強(qiáng)類型化的代碼可以避免運(yùn)行時(shí)錯(cuò)誤;智能感知會(huì)工作得更好。雖然使用泛型已經(jīng)有非常充分的理由,不過(guò)使用泛型還有更多的優(yōu)點(diǎn):性能和代碼重用。
將泛型技術(shù)引入.net框架的一個(gè)主要原因是為了提高性能。比如集合類可以比以前工作得更快,因?yàn)榫幾g器能夠針對(duì)集合所儲(chǔ)存的類型進(jìn)行優(yōu)化。下面的代碼比較了數(shù)組、arraylist以及泛型list的性能:
 txtoutput.text = "performance" & vbcrlf
 
 const iterations as integer = 5000000
 perftime.start()
 dim myarray(iterations) as integer
 for i as integer = 0 to iterations - 1
 myarray(i) = i
 next
 dim elapsed as integer = perftime.stop
 txtoutput.text &= "array time: " & elapsed & vbcrlf
 myarray = nothing
 gc.collect()
 
 perftime.start()
 dim myarraylist as new arraylist
 for i as integer = 0 to iterations - 1
 myarraylist.add(i)
 next
 elapsed = perftime.stop
 txtoutput.text &= "arraylist time: " & elapsed & vbcrlf
 myarraylist = nothing
 gc.collect()
 
 perftime.start()
 dim mylist as new list(of integer)
 for i as integer = 0 to iterations - 1
 mylist.add(i)
 next
 elapsed = perftime.stop
 txtoutput.text &= "list time: " & elapsed & vbcrlf
 mylist = nothing
 gc.collect()
這段代碼在固定長(zhǎng)度的數(shù)組中儲(chǔ)存了500萬(wàn)個(gè)數(shù)值,同時(shí)也在自動(dòng)增長(zhǎng)的arraylist和泛型list中儲(chǔ)存同樣多的數(shù)值,性能數(shù)值看起來(lái)非常有趣:
array 時(shí)間: 344
arraylist時(shí)間: 4656
list時(shí)間: 797
有特定類型的定長(zhǎng)數(shù)組有無(wú)與倫比的速度,而且不需要為改變大小付出代價(jià)。而集合類型的大小都是自動(dòng)增長(zhǎng),如果有固定數(shù)組1/2的性能是相當(dāng)不錯(cuò)的。接下來(lái)看看arraylist,非常不幸,只有固定數(shù)據(jù)1/10的性能。問(wèn)題出在arraylist被設(shè)計(jì)成儲(chǔ)存引用型變量,integer是值類型,在儲(chǔ)存到arraylist以前要經(jīng)過(guò)“裝箱”操作,將integer轉(zhuǎn)為object型。裝箱的代價(jià)是非常昂貴的,所以當(dāng)你儲(chǔ)存值類型數(shù)據(jù)(如integer、date、boolean以及你自己創(chuàng)建的structure等)時(shí),使用泛型將獲得非常可觀的性能提升。
更多關(guān)于“裝箱”和“拆箱”操作的信息,請(qǐng)參見(jiàn)msdn庫(kù)中的“裝箱轉(zhuǎn)換”和“拆箱轉(zhuǎn)換”
創(chuàng)建泛型類型和方法
并不是只能使用visual basic.net提供的泛型類型,你可以創(chuàng)建你自己的泛型類型和方法。
泛型方法
當(dāng)你想實(shí)現(xiàn)一些不與特定類型相關(guān)的一般算法時(shí),你可能想創(chuàng)建泛型方法。舉個(gè)例子,典型的冒泡排序需要遍歷數(shù)組中的所有項(xiàng)目,兩兩比較,并交換需要排序的數(shù)值。
如果你已經(jīng)確定只要進(jìn)行整數(shù)的排序,你可以簡(jiǎn)單地編寫一個(gè)只能用于integer類型的swap方法。但是如果你想能夠排序任何類型,你就可以編寫一個(gè)泛型swap方法如下:
private sub swap(of itemtype) _
 (byref v1 as itemtype, byref v2 as itemtype)
 
 dim temp as itemtype
 temp = v1
 v1 = v2
 v2 = temp
end sub
注意“of itemtype”,當(dāng)swap方法被調(diào)用時(shí),除了必須提供所需的參數(shù),還必須傳入一個(gè)數(shù)據(jù)類型。這個(gè)數(shù)據(jù)類型會(huì)代替任何實(shí)例中的itemtype。下面的例子調(diào)用了swap:
swap(of integer)(v1, v2)
這條語(yǔ)句告訴swap方法它將交換的是integer類型。如果你回過(guò)頭去看看swap的代碼,這條語(yǔ)句的意思就是讓jit將所有的itemtype換成integer,這個(gè)swap方法實(shí)際上已經(jīng)被jit重寫成:
private sub swap(byref v1 as integer, byref v2 as integer)
 dim temp as integer
 temp = v1
 v1 = v2
 v2 = temp
end sub
這是實(shí)際執(zhí)行的代碼,jit生成一個(gè)專用于integer類型的方法。如果你接下來(lái)想要排序字符串類型,你就可以用另一swap的調(diào)用如下:
swap(of string)(v1, v2)
當(dāng)方法執(zhí)行的時(shí)候,jit會(huì)生成另一個(gè)版本的swap,這次是特定成string類型的:
private sub swap(byref v1 as string, byref v2 as string)
 dim temp as string
 temp = v1
 v1 = v2
 v2 = temp
end sub
下面是一個(gè)使用泛型swap的冒泡排序的完整例子:
private sub btnsortintegers_click(byval sender as system.object, byval e as system.eventargs) handles btnsortintegers.click
 dim ints(9) as integer
 dim r as new random
 for i as integer = 0 to 9
 ints(i) = r.next(1, 100)
 next
 
 ' 冒泡排序
 for j as integer = 0 to 9
 for k as integer = 9 to 1 step -1
 if ints(k) < ints(k - 1) then
 swap(of integer)(ints(k), ints(k - 1))
 end if
 next
 next
 
 txtoutput.text = "sort integers" & vbcrlf
 for i as integer = 0 to 9
 txtoutput.text &= ints(i) & vbcrlf
 next
end sub
 
泛型類型
最后一點(diǎn),你能夠創(chuàng)建完全泛型的類型,使用這種“of itemtype”方法創(chuàng)建類的聲明如下:
public class someclass(of itemtype)
 
 private internalvar as itemtype
 public function somemethod(byval value as itemtype) as itemtype
 end function
 
end class
這段代碼對(duì)類的作用與方法是相同的。jit編譯器會(huì)簡(jiǎn)單地將實(shí)例中的itemtype替換成實(shí)例化時(shí)特別指明的類型。
約束
泛型技術(shù)還支持一種叫做約束的特性。這項(xiàng)功能確保在指定類型的時(shí)候,傳入的類型最起碼要實(shí)現(xiàn)某些功能。比如你要實(shí)現(xiàn)一種排序算法,你需要確保傳入的類型能夠?qū)崿F(xiàn)icomparible接口。你可以用約束來(lái)完成這個(gè)設(shè)想:
public class someclass(of itemtype as icomparible)
 
 public function somemethod(byval value as itemtype) as itemtype
 end function
 
end class
 
結(jié)論
泛型技術(shù)相對(duì)于以object為基礎(chǔ)的集合提供了很多好處,首先,泛型類是強(qiáng)類型的,這就確保所有的錯(cuò)誤在編譯時(shí)能夠發(fā)現(xiàn)。強(qiáng)類型還可以讓智能感知提供更多方便。泛型還能讓你簡(jiǎn)化代碼,讓你的算法可以作用于多種類型。最后,泛型集合要比以object為基礎(chǔ)的集合快得多,特別是用于值類型時(shí)。