При создании 3D-массива на C#, который является лучшим способом его создания?C# Массив [a, b, c] и массив [a] [b] [c]?
Массив [а, б, в] или массив [а] [Ь] [с]?
Или это просто вопрос предпочтения?
При создании 3D-массива на C#, который является лучшим способом его создания?C# Массив [a, b, c] и массив [a] [b] [c]?
Массив [а, б, в] или массив [а] [Ь] [с]?
Или это просто вопрос предпочтения?
Это две принципиально разные конструкции. Если вы удовлетворите свои требования лучше, чем другие, предпочитайте это, как само собой разумеющееся.
Массив [а, б, в] является трехмерным, прямоугольный массив. Это означает, что все элементы существуют, но в зависимости от ваших потребностей могут быть малонаселенными. Массив [a] [b] [c] представляет собой трехмерный зазубренный массив или массив массивов массивов.
При прочих равных условиях, я считаю, что однажды прочитал источник (который я считал авторитетным в то время), что зубчатый массив обычно предпочтительнее прямоугольного массива. Я не помню, была ли причиной какая-то причина, связанная с производительностью (кэширование?) Или что-то еще.
Если вы хотите иметь прямоугольный массив, тогда массив [a, b, c] должен быть быстрее.
Если вам нужна другая форма, вы должны использовать Array [a] [b] [c] - в этом случае первая строка может содержать, например, 5 объектов, вторых 6 объектов и т. Д.
a jagged Array [a] [b] [c] быстрее – stmax
Невыровненный массив (Array[a][b][c]
) немного быстрее. Однако для этого требуется немного больше кода.
прямоугольные массивы проще для инициализации, но неровные массивы быстрее. причина, по которой зубчатые массивы быстрее, заключается в том, что существуют промежуточные языковые инструкции, которые напрямую поддерживают одномерные массивы. сравнить следуют два разборками:
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% быстрее, чем версия прямоугольного массива (доступ с использованием последовательных, а также случайных индексов).
Спасибо, это satysfying ответ, но противный мне :) –
@henk: объяснить оптимизацию проверки диапазона, которая происходит/не выполняется в случае зубчатых/прямоугольных массивов более подробно? Я всегда думал, что ускорение связано с встроенными инструкциями IL для одномерных массивов ... – stmax
Этот источник, вероятно, является руководством по разработке .NET Framework или файлом справки FXCop. Оба предпочитают неровные массивы. –
Может ли кто-нибудь объяснить, почему массив с чередованием может быть быстрее, чем многомерный массив? Многомерный массив IMHO должен быть быстрее, потому что гораздо проще вычислить точный адрес объекта, который хранится в таком массиве. –
Все говорят, что зубчатые быстрее, но никто не говорит почему :) – Poma