.net – 使用array.resize而不是redim的原因
我知道“redim”比“Array.Resize”更旧,但是不明白将后者用于前者的原因.
除非添加“保留”修改器,否则无法比较
ReDim和
Array.Resize<T>.
Array.Resize不仅会分配新数组,还会将源数组中的所有项目复制到目标数组. 没有Preserve修饰符的ReDim只会分配一个新数组.源数组中的所有项都将丢失. 基本上这个: Dim a As String() = {"item1","item2"} ReDim a(4 - 1) 'Double the size 'At this point,a contains 4 null references. ……等于这个: Dim a As String() = {"item1","item2"} a = New String(4 - 1) {} 'Double the size 'At this point,a contains 4 null references. 您可以通过检查发布配置中生成的CIL代码来验证这一点,并查找0x8D – newarr <etype>指令.通过了解这一点,很明显为什么它比Array.Resize< T>更快. 因此,让我们比较ReDim Preserve和Array< T>.
让我们创建两个方法并查看CIL代码. VB.NET Private Sub ResizeArray1(Of T)(ByRef a As T(),size As Int32) ReDim Preserve a(size - 1) End Sub Private Sub ResizeArray2(Of T)(ByRef a As T(),size As Int32) Array.Resize(a,size) End Sub CIL .method private static void ResizeArray1<T>(!!T[]& a,int32 size) cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldarg.0 L_0002: ldind.ref L_0003: ldarg.1 L_0004: ldc.i4.1 L_0005: sub.ovf L_0006: ldc.i4.1 L_0007: add.ovf L_0008: newarr !!T L_000d: call class [mscorlib]System.Array [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Utils::CopyArray(class [mscorlib]System.Array,class [mscorlib]System.Array) L_0012: castclass !!T[] L_0017: stind.ref L_0018: ret } .method private static void ResizeArray2<T>(!!T[]& a,int32 size) cil managed { .maxstack 8 L_0000: ldarg.0 L_0001: ldarg.1 L_0002: call void [mscorlib]System.Array::Resize<!!T>(!!0[]&,int32) L_0007: ret } 如您所见,ReDim Preserve最终作为Microsoft.VisualBasic.CompilerServices.Utils.CopyArray的调用指令.现在,如果您检查CopyArray(源代码在RS不可用)和Array.Resize<T>,您将看到两个方法最终都作为Array.Copy<T>的调用指令,即CLR方法. 所以人们可以争辩说它们本质上都是“相同的”,并且快速的benckmark(在这篇文章的最后可用)似乎证实了这一点. 但是,正如Hans Passant正确指出的那样,无论何时需要操作数组,都应该使用List<T>. 基准
Option Strict On Public Module Program Friend Sub Main() Console.WriteLine("Warming up...") Program.Benchmark(iterations:=10,maxSize:=1000,warmUp:=True) Console.WriteLine("Warmup completed. Measurement started...") Program.Benchmark(iterations:=10,maxSize:=100000,warmUp:=False) Console.WriteLine() Console.WriteLine("Measurement completed. Press any key to exit.") Console.ReadKey() End Sub Private Sub Benchmark(iterations As Int32,maxSize As Int32,warmUp As Boolean) Dim watch As Stopwatch Dim a As String() 'BY: EMPTY SOURCE ARRAY --------------------------------- 'Resize array #1 watch = Stopwatch.StartNew() For i As Int32 = 1 To iterations For n As Int32 = 1 To maxSize a = Program.CreateArray(Of String)(0) Program.ResizeArray1(a,n) Next Next watch.Stop() If (Not warmUp) Then Console.WriteLine() Console.WriteLine(String.Format("R E S U L T")) Console.WriteLine() Console.WriteLine(String.Format("Iterations: {0}",iterations)) Console.WriteLine(String.Format(" MaxSize: {0}",maxSize)) Console.WriteLine() Console.WriteLine("Empty source array:") Console.WriteLine() Console.WriteLine(New With {.Method = "ResizeArray1",.Time = watch.Elapsed.ToString()}) End If 'Resize array #2 watch = Stopwatch.StartNew() For i As Int32 = 1 To iterations For n As Int32 = 1 To maxSize a = CreateArray(Of String)(0) ResizeArray2(a,n) Next Next watch.Stop() If (Not warmUp) Then Console.WriteLine(New With {.Method = "ResizeArray2",.Time = watch.Elapsed.ToString()}) End If 'BY: GROWING SOURCE ARRAY ------------------------------- 'Resize array #1 watch = Stopwatch.StartNew() a = Program.CreateArray(Of String)(0) For i As Int32 = 1 To iterations For n As Int32 = 1 To maxSize Program.ResizeArray1(a,n) Next Next watch.Stop() If (Not warmUp) Then Console.WriteLine() Console.WriteLine("Growing source array:") Console.WriteLine() Console.WriteLine(New With {.Method = "ResizeArray1",.Time = watch.Elapsed.ToString()}) End If 'Resize array #2 watch = Stopwatch.StartNew() a = Program.CreateArray(Of String)(0) For i As Int32 = 1 To iterations For n As Int32 = 1 To maxSize Program.ResizeArray2(a,.Time = watch.Elapsed.ToString()}) End If End Sub Private Function CreateArray(Of T)(size As Int32) As T() Return New T(size - 1) {} End Function Private Sub ResizeArray1(Of T)(ByRef a As T(),size As Int32) ReDim Preserve a(size - 1) End Sub Private Sub ResizeArray2(Of T)(ByRef a As T(),size As Int32) Array.Resize(a,size) End Sub End Module (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |