在c#中,多维数组double[,]和数组的数组double[][]有什么区别?
如果有区别,每一种的最佳用途是什么?
在c#中,多维数组double[,]和数组的数组double[][]有什么区别?
如果有区别,每一种的最佳用途是什么?
当前回答
简单地说,多维数组类似于DBMS中的表。 Array of Array(锯齿状数组)允许每个元素保存另一个相同类型的可变长度数组。
因此,如果您确定数据结构看起来像一个表(固定的行/列),您可以使用多维数组。锯齿数组是固定的元素&每个元素可以容纳一个可变长度的数组
例如Psuedocode:
int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;
我们可以把上面的表格看成一个2x2的表格:
1 | 2 3 | 4
int[][] jagged = new int[3][];
jagged[0] = new int[4] { 1, 2, 3, 4 };
jagged[1] = new int[2] { 11, 12 };
jagged[2] = new int[3] { 21, 22, 23 };
可以把上面的代码看成每一行都有可变的列数:
1 | 2 | 3 | 4 11 | 12 21 | | 22, 23
其他回答
简单地说,多维数组类似于DBMS中的表。 Array of Array(锯齿状数组)允许每个元素保存另一个相同类型的可变长度数组。
因此,如果您确定数据结构看起来像一个表(固定的行/列),您可以使用多维数组。锯齿数组是固定的元素&每个元素可以容纳一个可变长度的数组
例如Psuedocode:
int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;
我们可以把上面的表格看成一个2x2的表格:
1 | 2 3 | 4
int[][] jagged = new int[3][];
jagged[0] = new int[4] { 1, 2, 3, 4 };
jagged[1] = new int[2] { 11, 12 };
jagged[2] = new int[3] { 21, 22, 23 };
可以把上面的代码看成每一行都有可变的列数:
1 | 2 | 3 | 4 11 | 12 21 | | 22, 23
多维数组是(n-1)维矩阵。
所以int[,] square = new int[2,2]是一个方阵2x2, int[,] cube = new int[3,3,3]是一个立方-方阵3x3。比例不是必需的。
交错数组只是数组的数组——每个单元格包含一个数组的数组。
所以MDA是成比例的,JD可能不是!每个单元格可以包含任意长度的数组!
除了其他答案之外,请注意,多维数组被分配为堆上的一个大块对象。这有一些含义:
Some multidimensional arrays will get allocated on the Large Object Heap (LOH) where their equivalent jagged array counterparts would otherwise not have. The GC will need to find a single contiguous free block of memory to allocate a multidimensional array, whereas a jagged array might be able to fill in gaps caused by heap fragmentation... this isn't usually an issue in .NET because of compaction, but the LOH doesn't get compacted by default (you have to ask for it, and you have to ask every time you want it). You'll want to look into <gcAllowVeryLargeObjects> for multidimensional arrays way before the issue will ever come up if you only ever use jagged arrays.
我正在解析ildasm生成的.il文件,以构建用于进行转换的程序集、类、方法和存储过程的数据库。我遇到了下面的问题,打断了我的解析。
.method private hidebysig instance uint32[0...,0...]
GenerateWorkingKey(uint8[] key,
bool forEncryption) cil managed
Serge Lidin于2006年出版的《Expert . net 2.0 IL汇编器》一书,第8章,原始类型和签名,149-150页解释了这一点。
<type>[]被称为<type>的Vector,
<type>[<bounds> [<bounds>**]]被称为<type>的数组
**表示可重复,[]表示可选。
示例:Let <type> = int32。
1) int32[……]是一个具有未定义的下界和大小的二维数组
2) int32[2…5]是一个下界为2,大小为4的一维数组。
3) int32[0, 0…]是一个下界为0且大小未定义的二维数组。
Tom
数组的数组(锯齿数组)比多维数组更快,可以更有效地使用。多维数组有更好的语法。
如果你使用交错数组和多维数组写一些简单的代码,然后用IL反汇编器检查编译后的程序集,你会发现从交错数组(或一维数组)中存储和检索是简单的IL指令,而多维数组的相同操作是方法调用,总是比较慢。
考虑以下方法:
static void SetElementAt(int[][] array, int i, int j, int value)
{
array[i][j] = value;
}
static void SetElementAt(int[,] array, int i, int j, int value)
{
array[i, j] = value;
}
他们的IL将如下:
.method private hidebysig static void SetElementAt(int32[][] 'array',
int32 i,
int32 j,
int32 'value') cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldelem.ref
IL_0003: ldarg.2
IL_0004: ldarg.3
IL_0005: stelem.i4
IL_0006: ret
} // end of method Program::SetElementAt
.method private hidebysig static void SetElementAt(int32[0...,0...] 'array',
int32 i,
int32 j,
int32 'value') cil managed
{
// Code size 10 (0xa)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: ldarg.3
IL_0004: call instance void int32[0...,0...]::Set(int32,
int32,
int32)
IL_0009: ret
} // end of method Program::SetElementAt
当使用锯齿状数组时,可以轻松地执行行交换和行大小调整等操作。也许在某些情况下使用多维数组会更安全,但即使Microsoft FxCop也告诉我们,当您使用锯齿数组来分析您的项目时,应该使用锯齿数组而不是多维数组。