使用array.resize而不是redim的原因

基因

我知道“ redim”比“ Array.Resize”更旧,但不了解使后者更好地用于前者的原因。

比昂·罗格·克林佐(Bjørn-RogerKringsjå)

除非添加修饰符,否则可能无法比较ReDimArray.Resize <T> Preserve

Array.Resize 将不仅分配一个新数组,还将源数组中的所有项目复制到目标数组。

ReDim没有Preserve修饰符的将只分配一个新数组。源数组中的所有项目均丢失。

所以基本上这样:

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 PreserveArray<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>,您将看到这两种方法最终都作为CLR方法Array.Copy <T>的调用指令而结束

因此,可以认为它们本质上都是“相同的”,并且快速的Benckmark(在本文末尾提供)似乎可以证实这一点。

但是,正如Hans Passant正确指出的那样,无论何时需要操纵数组,都应该使用List <T>


基准

迭代次数:10个最大
尺寸:100000

空源数组:

{方法= ResizeArray1,时间= 00:00:05.6533126}
{方法= ResizeArray2,时间= 00:00:05.6973607}

不断增长的源数组:

{方法= ResizeArray1,时间= 00:01:42.6964858}
{方法= ResizeArray2,时间= 00:01:42.1891668}

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, n)
            Next
        Next

        watch.Stop()

        If (Not warmUp) Then
            Console.WriteLine(New With {.Method = "ResizeArray2", .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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用| =而不是=的特定原因

来自分类Dev

使用argv [argc + 1]而不是argv []的原因是什么

来自分类Dev

使用Array.map而不是array.map

来自分类Dev

而不是 $.each 想使用 Array.find

来自分类Dev

是什么原因导致尝试在React中使用Vanilla Tilt的原因是“ TypeError:Object(...)不是一个函数”?

来自分类Dev

使用空链接调用js而不是其他html元素的原因

来自分类Dev

由于平台遗留原因,请使用sleep而不是thread.join()

来自分类Dev

是否出于技术原因在Rails URL中不使用_url而不是_path?

来自分类Dev

在属性中使用Func <T>而不是简单T的原因可能是什么

来自分类Dev

使用空格而不是制表符进行缩进的客观原因?

来自分类Dev

人们在get中使用属性的原因是什么?组; 而不是田地?

来自分类Dev

在React中使用数据URI而不是小于10kb的图像的路径的原因是什么?

来自分类Dev

XAML控件使用“可见性”类型而不是普通的“布尔”的实际原因是什么?

来自分类Dev

当foo被声明为可变的时,要求使用&mut foo而不是&foo的原因是什么?

来自分类Dev

为什么使用array($ this,'function')而不是$ this-> function()

来自分类Dev

使用array.splice时,未定义不是函数

来自分类Dev

什么时候适合使用ArrayObject而不是Array

来自分类Dev

使用array_combine()保留重复项(而不是删除它们)

来自分类Dev

如何正确使用array.prototype.filter()而不是.map()

来自分类Dev

是否可以在THREE.BufferGeometry中使用Float64Array而不是Float32Array

来自分类Dev

是否可以在THREE.BufferGeometry中使用Float64Array而不是Float32Array

来自分类Dev

为什么font-awesome建议使用<i>元素而不是<span>元素?有具体原因可取吗?

来自分类Dev

C#/ C ++ CLI:对Array.Resize使用监视器锁定

来自分类Dev

在Excel VBA中使用多维数组进行ReDim Preserve

来自分类Dev

为了强制转换指针数组(例如* array []),为什么要使用(void **)而不是(void *)

来自分类Dev

Postgres:使用ARRAY_AGG和HAVING(而不是WHERE)过滤结果

来自分类Dev

为什么在使用is_array检查时,laravel中的get()函数返回的不是数组

来自分类Dev

Laravel-当我不再使用数组时发生``array_merge():参数#2不是数组''

来自分类Dev

可以使用Array而不是arrayList在recyclerView中显示项目吗?

Related 相关文章

  1. 1

    使用| =而不是=的特定原因

  2. 2

    使用argv [argc + 1]而不是argv []的原因是什么

  3. 3

    使用Array.map而不是array.map

  4. 4

    而不是 $.each 想使用 Array.find

  5. 5

    是什么原因导致尝试在React中使用Vanilla Tilt的原因是“ TypeError:Object(...)不是一个函数”?

  6. 6

    使用空链接调用js而不是其他html元素的原因

  7. 7

    由于平台遗留原因,请使用sleep而不是thread.join()

  8. 8

    是否出于技术原因在Rails URL中不使用_url而不是_path?

  9. 9

    在属性中使用Func <T>而不是简单T的原因可能是什么

  10. 10

    使用空格而不是制表符进行缩进的客观原因?

  11. 11

    人们在get中使用属性的原因是什么?组; 而不是田地?

  12. 12

    在React中使用数据URI而不是小于10kb的图像的路径的原因是什么?

  13. 13

    XAML控件使用“可见性”类型而不是普通的“布尔”的实际原因是什么?

  14. 14

    当foo被声明为可变的时,要求使用&mut foo而不是&foo的原因是什么?

  15. 15

    为什么使用array($ this,'function')而不是$ this-> function()

  16. 16

    使用array.splice时,未定义不是函数

  17. 17

    什么时候适合使用ArrayObject而不是Array

  18. 18

    使用array_combine()保留重复项(而不是删除它们)

  19. 19

    如何正确使用array.prototype.filter()而不是.map()

  20. 20

    是否可以在THREE.BufferGeometry中使用Float64Array而不是Float32Array

  21. 21

    是否可以在THREE.BufferGeometry中使用Float64Array而不是Float32Array

  22. 22

    为什么font-awesome建议使用<i>元素而不是<span>元素?有具体原因可取吗?

  23. 23

    C#/ C ++ CLI:对Array.Resize使用监视器锁定

  24. 24

    在Excel VBA中使用多维数组进行ReDim Preserve

  25. 25

    为了强制转换指针数组(例如* array []),为什么要使用(void **)而不是(void *)

  26. 26

    Postgres:使用ARRAY_AGG和HAVING(而不是WHERE)过滤结果

  27. 27

    为什么在使用is_array检查时,laravel中的get()函数返回的不是数组

  28. 28

    Laravel-当我不再使用数组时发生``array_merge():参数#2不是数组''

  29. 29

    可以使用Array而不是arrayList在recyclerView中显示项目吗?

热门标签

归档