英语原文共 32 页,剩余内容已隐藏,支付完成后下载完整资料
第14章:数组
概述
数组是一种机制,允许你将多个项视为单个集合。Microsoft.net通用语言运行时(CLR)支持一维数组、多维数组和交错数组(即数组的数组)。所有数组类型都隐式地派生自System.Array,System.Array本身派生自System.Object。这意味着数组始终是分配在托管堆上的引用类型,应用程序的数组变量包含的是一个指向数组的引用,而不是数组本身。下面的代码更清楚地说明了这一点:
Int32[] myIntegers;//声明对数组的引用
myIntegers = new Int32[100];//创建一个包含100个int32的数组
在第一行中,myIntegers是一个变量,它能够指向一个元素类型为Int32的一维数组。最初,myIntegers将被设置为null,因为我们没有为其分配数组。第二行代码分配一个包含100个Int32的数组;所有Int32元素值都初始化为0。尽管int32是值类型,但足够容纳这些值的内存块是从托管堆中分配的。内存块包含100个未装箱的Int32值。这个内存块的地址被返回并保存在变量myIntegers中。
你还可以创建引用类型的数组:
Control[] myControls;//声明对数组的引用
myControls = new Control[50];//创建一个含有50个Control引用的数组
在第一行中,myControls是一个能够指向元素为Control引用的一维数组的变量。最初,myControls将被设置为null,因为我没有为其分配数组。第二行分配一个包含50个Control引用的数组;所有这些引用都初始化为null。因为Control是引用类型,所以创建数组只创建引用;此时还没有创建实际的对象。这个内存块的地址被返回并保存在变量myControls中。
图14-1显示了值类型数组和引用类型数组在托管堆中的情况。
在图中,myControls数组显示了以下行执行后的结果:
myControls[1] = new Button();
myControls[2] = new TextBox();
myControls[3] = myControls[2]; // 两个元素指向同一个对象
myControls[46] = new DataGrid();
myControls[48] = new ComboBox();
myControls[49] = new Button();
通用语言规范(CLS)遵从性要求所有数组都是0基数组。这允许用c#编写的方法创建一个数组,并将该数组的引用传递给用另一种语言(如Microsoft Visual Basic)编写的代码。此外,由于到目前为止,0基数组是最常见的数组,微软已经花费了大量时间来优化它们的性能。然而,CLR也支持非0基数组,尽管不鼓励使用它们。对于那些不关心性能或跨语言可移植性的人,我将在本节后面演示如何创建和使用非0基数组。
注意在图14-1中,每个数组都有一些与之相关的额外负载信息。这个信息包含数组的秩(维数)、数组每个维的下界(大多数时候总是0)和每个维的长度。负载信息还包含数组中每个元素的类型。稍后,我将介绍允许查询这些负载信息的方法。
到目前为止,我已经展示了如何创建一维数组的。如果可能,我们应该尽可能坚持使用一维0基数组,有时也称为SZ数组或向量。一维0基数组的性能最好,因为我们可以使用特定的IL指令(如newarr、ldelem、ldelema、ldlen和stelement)来操作它们。但是,如果您喜欢使用多维数组,您可以这样做。下面是一些多维数组的例子:
//创建一个Double类型的二维数组。
Double[,] myDoubles = new Double[10, 20];
// 创建String类型的三维数组。
String[,,] myStrings = new String[5, 3, 10];
CLR还支持交错数组。一维0基交错数组和通常的一维0基数组具有相同的性能。然而,访问交错数组的元素意味着必须进行两次或多次数组访问。注意,交错数组与CLS是不兼容的——因为CLS不允许一个数组的元素类型为System.Array——所以不能在不同编程语言编写的代码之间传递。幸运的是,c#支持交错数组。下面是一些如何创建多边形数组的例子,其中每个多边形包含一个Point实例数组:
// 创建一个元素为Point数组的一维数组。
Point[][] myPolygons = new Point[3][];
// myPolygons[0]指向一个包含10个Point实例的数组。
myPolygons[0] = new Point[10];
// myPolygons[1] 指向一个包含20个Point实例的数组。
myPolygons[1] = new Point[20];
// myPolygons[2] 指向一个包含30个Point实例的数组。
myPolygons[2] = new Point[30];
// 显示第一个多边形中的Point。
for (Int32 x = 0, l = myPolygons[0].Length; x lt; l; x )
Console.WriteLine(myPolygons[0][x]);
注意
CLR会验证数组中的索引是否有效。换句话说,我们不能创建一个包含100个元素的数组(索引0到99),然后尝试访问索引为100或-5的元素。这样做会导致一个System.IndexOutOfRangeException 异常抛出。允许访问数组范围之外的内存将破坏类型安全,并造成潜在的安全漏洞,而CLR不允许可验证代码中出现这样的行为。通常,索引检查带来的性能损失是微不足道的,因为JIT (just-in-time)编译器通常在一次循环执行之前只检查一次数组边界,而不是在每次循环迭代时都检查一次。但是,如果您仍然担心CLR的索引检查对性能的影响,那么您可以使用c#中的非安全代码来访问该数组。本章后面的“快速数组访问”小节将演示如何实现这一点。
所有数组的基类System.Array
System.Array类型提供了几个静态成员和实例成员。因为所有数组都是隐式地继承自System.Array,这些成员可用于操作值类型或引用类型的数组。还要注意,Array实现了几个接口:ICloneable、IEnumerable、ICollection和IList。这些接口允许在许多不同的场景中方便地使用数组。
表14-1总结了System.Array提供的几种方法及实现的几种接口。
表14-1:System.Array的成员
成员 |
成员类型 |
描述 |
Rank |
只读实例属性 |
返回数组中的维数。 |
GetLength |
实例方法 |
返回数组的指定维度中的元素数。 |
Length |
只读实例属性 |
返回数组中元素的总数。 |
GetLowerBound |
实例方法 |
返回数组中指定维度的下界。这几乎总是0。 |
GetUpperBound |
实例方法 |
返回数组中指定维数的上限。大多数时候为指定维数的元素个数减1. |
IsReadOnly |
只读实例属性 |
指示数组是否只读。对于数组,这总是false。 |
IsSynchronized |
只读实例属性 |
指示数组访问是否线程安全。对于数组,这总是false。 |
SyncRoot |
只读实例属性 |
检索可用于同步对数组的访问的对象。对于数组,这始终是对数组本身的引用。 |
IsFixedSize |
只读实例属性 |
指示数组是否为固定大小。对于数组,这总是true。 |
GetValue |
实例方法 |
返回对位于数组中指定位置的元素的引用。如果数组包含值类型,则返回值引用元素的装箱形式的拷贝。只有在设计时不知道数组中的维数时,才需要这种很少使用的方法。 |
SetValue |
实例方法 |
设置位于数组中指定位置的元素。只有在设计时不知道数组中的维数时,才需要这种很少使用的方法 |
GetEnumerator |
实例方法 |
为数组返回一个IEnumerator。这允许使用c#的foreach语句(或其他语言中的等效语句)。对于多维数组,枚举器遍历所有元素的时候,最右边的维度变化最快。 |
Sort |
静态方法 |
对一个数组、两个数组或数组的一部分中的元素进行排序。数组元素类型必须包含IComparer接口,或者必须传递一个实现了IComparer接口的对象。 |
BinarySearch |
静态方法 |
使用二分搜索算法在指定的数组中搜索指定的元素。这个方法假设数组的元素是排好序的。数组元素类型必须实现IComparer接口。通常在调用BinarySearch之前使用Sort方法 |
IndexOf |
静态方法 |
返回一维数组或其中一部分中某个值的第一次出现的索引 |
LastIndexOf |
静态方法 |
返回一维数组或其中一部分中某个值的最后一次出现的索引 |
Reverse |
静态方法 |
反转指定一维数组或其中一部分中的元素的顺序。 |
Clone |
实例方法 |
创建一个新数组,它是源数组的一个浅拷贝。 |
CopyTo |
实例方法 |
将元素从一个数组复制到另一个数组。 |
Copy |
静态方法 |
将一个数组的一个部分复制到另一个数组,并根据需要执行适当的转型。 |
Clear |
静态方法 |
将数组中的部分元素设为0或null空引用。 |
CreateInstance |
静态方法 |
创建数组的实例。这个很少使用的方法允许您动态(在运行时)定义任何类型、任何维数和任何上下限的数组。 |
Initialize |
实例方法 |
为值类型数组中的每个元素调用默认构造函数。如果数组中的元素是引用类型,则此方法不执行任何操作。c#不允许您为值类型定义默认构造函数,因此此方法对c#结构的数组没有用处。此方法主要用于编译器供应商。 |
数组的转型
对于元素为引用类型的数组,CLR允许您隐式地将源数组的元素类型转换为另一种类型。要使转换成功,这两种数组类型必须具有同样的维数,并且必须存在从源数组元素类型到目标数组元素类型的隐式或显式转换。CLR不允许将元素为值类型的数组强制转换为任何其他类型。(然而,通过使用Array.Copy,则可以创建具有所需效果的新数组)。下面的代码演示了数组强制转换是如何工作的:
// 创建一个二维FileStream数组。
FileStream[,] fs2dim = new FileStream[5, 10];
/
全文共29038字,剩余内容已隐藏,支付完成后下载完整资料
资料编号:[793]
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。