C#数组讨论一
--------------------System.object [,]与System. object [][]之间的区别
二维数组,在c#中经常会用到,但是今天细细一复习,觉得还是有很多东西自己没有搞清楚。
一:System.Int32[,]
请看以下第一个例子:
int[,] grades = new int[,]
{
{1, 82, 74, 89, 100},
{2, 93, 96, 85, 86},
{3, 83, 72, 95,89},
{4, 91, 98, 79, 99}
};
这是一个二维数组的例子。
也可以定义为
int[,] grades = new int[4, 5];
然后再使用for循环赋值。
for (int i = 0; i < grades.GetLength(0);i++ )
{
for (int j = 0; j < grades.GetLength(1); j++)
{
//可用任何赋值方法此处仅为举例
grades[i, j] = i + j;
}
}
第一个需要关注的东西出现了:
public int GetLength(int dimension);
// Gets a 32-bit integer that represents the number of elements in the specified
// dimension of the System.Array.
意思是获取一个表示System.Array指定维度中的元素个数的一个32位int型数据。
此处第零维的个数grades.GetLength(0)为4,第一维的个数grades.GetLength(1)为5。
Console.WriteLine(grades.Length);
执行这句话就是获取数组中的元素总个数,不管多少维数组,直接返回元素总个数。
我们定义的这个数组在.net中到底是什么类型呢?
Console.WriteLine(grades.GetType());
输出为:System.Int32[,]。
在此处我们无法获知内存是如何具体分配的,但是通过其类型我们知道:
首先它是一个数组,是System.Array类的一个实例。所以首先现在栈上分配一个四个字节大小的空间来存储这个实例的地址,这个地址就是我们看到的命名,也就是一个标识就是grades。
其次,是System.Array在内存托管堆中的分配。对于System.Array中的一些辅助的私有成员我们不去追究其细节,就知道它们在分配数据空间之前已经被分配了。
最后,分配的是数据区域,由于我们在定义这个数组的时候,要么使用直接赋值,要么采用定义好维度及各个维度的上限。对于直接赋值的方式,系统会根据赋值的情况确定维度及各个维度的上限。
对于分配内存,根据c++的经验,会是一个维度一个维度的分配,一个连续的数据带,根据索引的不同,地址偏移,就获取了对应的元素。
如下图:
二:System. object [][]
请看以下例子:
int[][] jagged = new int[3][];
jagged[0] = new int[2] { 1, 2 };
jagged[1] = new int[6] { 3, 4, 5, 6, 7, 8 };
jagged[2] = new int[3] { 9, 10, 11 };
直觉上我们知道,这是一个二维数组。
事实呢:我们来测试一下
Console.WriteLine(jagged.Length);
Console.WriteLine(jagged.Rank);
Console.WriteLine(jagged.GetType());
输出分别是:
3
1
System. Int32 [][]
以上输出清楚地告诉我们,这是一个一维数组,一共有3个元素。
那么System. Int32 [][]和System.Int32[,]区别在哪里。
首先:
System. Int32 [][]在栈中分配的内存是4个字节的一个引用,同样这个引用指向一个System.Array对象。
这个System.Array对象中一共有3个元素,每个元素又是一个4个字节的引用,每个元素都指向一个新的System.Array对象。
内存分布如下图: