2010-03-09 157 views

回答

7
  1. 这些是两个根本不同的构造。如果一个人比另一个更适合你的要求,那么当然更喜欢它。数组[a,b,c]是一个三维的矩形数组。这意味着所有元素都存在,但取决于您的需求,可能人口稀少。数组[a] [b] [c]是三维锯齿状数组或阵列数组。我相信我曾经读过一个资料来源(那时我认为是权威的),锯齿状的数组通常比矩形数组更好。我不记得究竟是因为某种与性能相关的原因(缓存?)还是其他原因。

+1

该来源可能是.NET框架设计指南或FXCop帮助文件。两者都喜欢锯齿状的阵列。 – 2010-03-09 22:45:58

+1

有人可以解释为什么参差不齐的数组可以比多维数组更快吗? 恕我直言,多维数组应该更快,因为计算存储在此数组中的对象的确切地址要容易得多。 – 2010-03-09 22:49:31

+0

每个人都说锯齿速度更快,但没有人告诉我为什么:) – Poma 2010-03-09 23:18:18

0

如果你想要'矩形'数组,那么数组[a,b,c]应该更快。
如果您需要其他形状,那么您应该使用Array [a] [b] [c] - 在这种情况下,第一行可以包含例如5个对象,第二个6个对象等等。

+0

一个锯齿阵列[a] [b] [c]更快 – stmax 2010-03-09 23:10:20

1

锯齿阵列(Array[a][b][c])速度稍快。它需要更多的代码来创建。

6

矩形数组更容易初始化,但锯齿形数组更快。锯齿状数组更快的原因是因为存在直接支持一维数组的中间语言指令。比较遵循两个反汇编:

C#的方法:

public static int A() 
{ 
    int[,] a = new int[5, 5]; 
    return a[3, 4]; 
} 

编译为:

.method public hidebysig static int32 A() cil managed 
{ 
    .maxstack 3 
    .locals init (
     [0] int32[0...,0...] a) 
    L_0000: ldc.i4.5 
    L_0001: ldc.i4.5 
    L_0002: newobj instance void int32[0...,0...]::.ctor(int32, int32) 
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: ldc.i4.3 
    L_000a: ldc.i4.4 
    L_000b: call instance int32 int32[0...,0...]::Get(int32, int32) 
    L_0010: ret 
} 

和C#方法:

public static int B() 
{ 
    int[][] a = null; 
    return a[3][4]; 
} 

编译为:

.method public hidebysig static int32 B() cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] int32[][] a) 
    L_0000: ldnull 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.3 
    L_0004: ldelem.ref 
    L_0005: ldc.i4.4 
    L_0006: ldelem.i4 
    L_0007: ret 
} 

,你可以看到的第一种方法使用(慢)方法调用来获得一个数组项的值:

call instance int32 int32[0...,0...]::Get(int32, int32) 

而第二个使用(快得多)ldelem IL指令:

L_0004: ldelem.ref 
L_0005: ldc.i4.4 
L_0006: ldelem.i4 

这是使用VS2008在发布模式下编译的。基准测试显示锯齿阵列版本比矩形阵列版本快25%左右(使用顺序以及随机索引进行访问)。

+0

谢谢,这是令人满意的答案,但违反我的意愿:) – 2010-03-10 13:34:13

+0

@henk:你能解释在更详细的锯齿状/矩形阵列情况下发生的/不发生的范围检查优化?我一直认为加速是由于一维阵列的内置IL指令引起的...... – stmax 2010-03-10 20:29:49

相关问题