2010-03-09 7 views

ответ

7
  1. Это две принципиально разные конструкции. Если вы удовлетворите свои требования лучше, чем другие, предпочитайте это, как само собой разумеющееся.

    Массив [а, б, в] является трехмерным, прямоугольный массив. Это означает, что все элементы существуют, но в зависимости от ваших потребностей могут быть малонаселенными. Массив [a] [b] [c] представляет собой трехмерный зазубренный массив или массив массивов массивов.

  2. При прочих равных условиях, я считаю, что однажды прочитал источник (который я считал авторитетным в то время), что зубчатый массив обычно предпочтительнее прямоугольного массива. Я не помню, была ли причиной какая-то причина, связанная с производительностью (кэширование?) Или что-то еще.

+1

Этот источник, вероятно, является руководством по разработке .NET Framework или файлом справки FXCop. Оба предпочитают неровные массивы. –

+1

Может ли кто-нибудь объяснить, почему массив с чередованием может быть быстрее, чем многомерный массив? Многомерный массив IMHO должен быть быстрее, потому что гораздо проще вычислить точный адрес объекта, который хранится в таком массиве. –

+0

Все говорят, что зубчатые быстрее, но никто не говорит почему :) – Poma

0

Если вы хотите иметь прямоугольный массив, тогда массив [a, b, c] должен быть быстрее.
Если вам нужна другая форма, вы должны использовать Array [a] [b] [c] - в этом случае первая строка может содержать, например, 5 объектов, вторых 6 объектов и т. Д.

+0

a jagged Array [a] [b] [c] быстрее – stmax

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 в режиме выпуска. benchmark показывает, что версия с зубчатым массивом примерно на 25% быстрее, чем версия прямоугольного массива (доступ с использованием последовательных, а также случайных индексов).

+0

Спасибо, это satysfying ответ, но противный мне :) –

+0

@henk: объяснить оптимизацию проверки диапазона, которая происходит/не выполняется в случае зубчатых/прямоугольных массивов более подробно? Я всегда думал, что ускорение связано с встроенными инструкциями IL для одномерных массивов ... – stmax

Смежные вопросы