.NET中数组的隐秘特性[6]

[入库:2005年8月18日] [更新:2007年3月25日]

本文简介:选择自 dy_2000_abc 的 blog


       通过下面的例子和图示,你可以更好的了解这些内部字段。下面的非托管代码的主要目的是确定上述的内部字段在内存中的分布。
using system;
namespace abc
{
 class class1
 {
  [stathread]
  static void main(string[] args)
  {
   int[] a=new int[5];
   byte[] a=getbytes(a,4);
   //输出数组a的长度(array length)
   console.writeline(bitconverter.toint32(a,0));
   
   int[,,] b=new int[2,3,4];
   // 4+8*rank(维度数): 4+3*8=28
   byte[] b=getbytes(b,28);
   //分别输出数组b的长度,第1,2,3维的长度和第1,2,3维的下限
   for (int i=0;i<28;i=i+4)
   console.writeline(bitconverter.toint32(b,i));
   console.readline();
  }
  static byte[] getbytes(int[] array,int count)
  {
   unsafe
   {
    byte[] b=new byte[count];
    byte *pb;
    fixed (int *p=&array[0])
     pb=(byte *)p;
    pb=pb-count;
    for (int i=0;i<count;i++)
    {
     b[i]=*pb++;
    }
    
    return b;
   }
  }
  static byte[] getbytes(int[,,] array,int count)
  {
   unsafe
   {
    byte[] b=new byte[count];
    byte *pb;
    fixed (int *p=&array[0,0,0])
     pb=(byte *)p;
    pb=pb-count;
    for (int i=0;i<count;i++)
    {
     b[i]=*pb++;
    }
    return b;
   }
  }
 }
}
      根据上面代码的运行结果,我们可以确定数组的内部字段在内存中的分布,如图1所示(我在许多条件下测试了数组各内部字段在内存中的分布,发现它们的排列顺序总是如图)。


图1

       对普通数组的访问必须检查几个内部成员,这会对性能造成一定的影响。一般地,我们有两种办法来优化普通数组的性能:一种是使用交错数组;另一种是使用非安全代码访问。

数组类型与分类
       如果两个数组有着相同的维度数和相同的元素类型,我们认为这两个数组具有相同的类型,与c/c++不同,这里每一维的上限和下限不予考虑,下面的代码说明了这点。一些方法(比如array.copy)在操作多维数组时,它们在内部将多维数组看作一个一维数组(数组长度是各维长度的总和)。
array a=array.createinstance(typeof(int),new int[2]{2,2},new int[2]{-1,-1});
array b=array.createinstance(typeof(int),new int[2]{3,3},new int[2]{-10,-2});
if (a.gettype().equals(b.gettype()))
console.writeline("数组a与b属于同一类型");
      具有不同维度数的交错数组属于不同的类型,比如:
int[][] a=new int[2][];
int[][][] b=new int[2][][];
      a与b是不同的类型。道理比较显然,我们可以认为交错数组的元素是数组,a与b的元素类型是不一样的,所以a与b属于不同的类型。比较有意思的是,基类array类型调用type.isarray()方法返回值是false,调用type.getelementtype()方法返回值是null。
      除了基本长度外,数组还包含了一些数据,如图1所示。值类型数组包含的是未装箱的结构(连续排列),引用类型数组则包含了指向引用对象的指针(连续排列)。另外,引用类型数组在指针数据块之前还有一个元素类型字段(elementtype)。读者也许会认为:通过数组的方法表可以获得有关元素类型的信息,这个字段显得有点多余了。其实不然,通过这个字段,可以迅速地获得类型信息,另外,这对于数组的其他特性,比如数组变异(array covariance),是非常重要的(后面会详细讲述这点)。
      如果数据是值类型,那么元素的长度与相应的值类型一样,引用类型则占用intptr.size个字节。intptr.size在win32系统中是4个字节,在64位系统中是8个字节。依据微软的文档记录,intptr.size与void *指针的本地字节数相同,但是在非win32的rotor包(比如mac和unix),不管cpu是什么,intptr.size总是8个字节。

类型

元素的字节长度

bool

1

byte

1

short

2

int

4

本文关键:数组 Array ArrayList .net
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top