不過經過以下測試後,效率應該不能說是使用泛型型別的理由!理由應該是「安全型別」,就像我們常看到的舉例:ArrayList及ArrayList(Of T)、IList或IList(Of T),也就是說ArrayList、IList是個什麼型別都可以包含進去的陣列。假設我程式是在做數值運算,但你放了一個「Hello World!」ArrayList、IList是接受的,這稱「不安全型別」。
而ArrayList(Of T)與IList(Of T)就不同,在宣告時可以指定任意型別給ArrayList(Of T)與IList(Of T),也就是那個T,例如:ArrayList(Of Integer)、IList(Of String),這樣宣告之後,當你在使用時,Visual Studio會自動幫你除錯,不用等到建置之後再來除錯,例如你在ArrayList放了一個「Hello World!」的字串,但ArrayList的宣告只能放Integer,所以你或Visual Studio都能很明確找出問題!
泛型型別 V.S 非泛型型別
以下使用主控台應用程式測試:
- 新增「主控台應用程式」
- 新增一個類別,使用Object來進行處理
- 新增一個類別,使用泛型來進行處理
- 在主控台應用程式撰寫測試程式碼
測試環境
軟體:- XP SP3
- Visual Studio 2008
- .Net Framework 2 (3.5 SP1)
- CPU:賽揚 2.0
- RAM:2 GB
類別Obj(使用Object)
Public Class Obj Public _v1 As Object Public _v2 As Object Public Sub New(ByVal v1 As Object, ByVal v2 As Object) _v1 = v1 _v2 = v2 End Sub End Class
類別Gen(使用泛型)
Module Module1 Sub Main() Dim i As Integer = 0 Dim v1 As String Dim v2 As String ' st:Star Time Dim st As DateTime = Now ' boxing、unboxing1百萬次,兩個數變共2百萬次 For i = 0 To 1000000 Dim oa As New Obj(1, 2) v1 = CType(oa._v1, String) v2 = CType(oa._v2, String) Next 'et:End Time Dim et As DateTime = Now Console.WriteLine("Obj1:{0}", (et - st).ToString) st = Now ' 泛型型別1百萬次,兩個數變共2百萬次 For i = 0 To 1000000 Dim ga As New Gen(Of String, String)("1", "2") v1 = ga._v1 v2 = ga._v2 Next et = Now Console.WriteLine("Gen1:{0}", (et - st).ToString) st = Now For i = 0 To 2000000 Dim oa As New Obj(1, 2) v1 = CType(oa._v1, String) v2 = CType(oa._v2, String) Next et = Now Console.WriteLine("Obj2:{0}", (et - st).ToString) st = Now For i = 0 To 2000000 Dim ga As New Gen(Of String, String)("1", "2") v1 = ga._v1 v2 = ga._v2 Next et = Now Console.WriteLine("Gen2:{0}", (et - st).ToString) st = Now For i = 0 To 3000000 Dim oa As New Obj(1, 2) v1 = CType(oa._v1, String) v2 = CType(oa._v2, String) Next et = Now Console.WriteLine("Obj3:{0}", (et - st).ToString) st = Now For i = 0 To 3000000 Dim ga As New Gen(Of String, String)("1", "2") v1 = ga._v1 v2 = ga._v2 Next et = Now Console.WriteLine("Gen3:{0}", (et - st).ToString) st = Now For i = 0 To 4000000 Dim oa As New Obj(1, 2) v1 = CType(oa._v1, String) v2 = CType(oa._v2, String) Next et = Now Console.WriteLine("Obj4:{0}", (et - st).ToString) st = Now For i = 0 To 4000000 Dim ga As New Gen(Of String, String)("1", "2!") v1 = ga._v1 v2 = ga._v2 Next et = Now Console.WriteLine("Gen4:{0}", (et - st).ToString) st = Now For i = 0 To 5000000 Dim oa As New Obj(1, 2) v1 = CType(oa._v1, String) v2 = CType(oa._v2, String) Next et = Now Console.WriteLine("Obj5:{0}", (et - st).ToString) st = Now For i = 0 To 5000000 Dim ga As New Gen(Of String, String)("1", "2!") v1 = ga._v1 v2 = ga._v2 Next et = Now Console.WriteLine("Gen5:{0}", (et - st).ToString) End Sub End Module
測試數據
Obj1:00:00:01.7968750
Gen1:00:00:00.1562500
Obj2:00:00:03.7343750
Gen2:00:00:00.2812500
Obj3:00:00:05.5000000
Gen3:00:00:00.4218750
Obj4:00:00:07.2968750
Gen4:00:00:00.5468750
Obj5:00:00:09.1093750
Gen5:00:00:00.6875000
我們以最後那個5百萬次的測試來看,中間有兩個變數,所以共進行了一千萬次,很明顯的,泛型型別的效率比需boxing、unboxing的效率快很多倍,但也看的出來.Net Framework在型別處理上是「非常快速」。
結論
我想很少有一支程式必須進行一千萬次的boxing與unboxing,平常的影響連可能連0.1秒都不到。數據證明一切,泛型能提供的率效是高於一般非泛型的多倍,但此差距只有在非常大量(千萬次以上)才明顯,但泛型能帶來型別安全才是我們主要考量因素。
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。