本页已使用福昕阅读器进行编辑。
福昕软件(C)2005-2007,版权所有,
仅供试用。
第5章
数组
如果需要使用同一类型的多个对象,就可以使用集合和数组。C# 用特殊的记号声明和使用数组。Array
类在后台发挥作用,为数组中元素的排序和过滤提供了几个方法。
使用枚举器,可以迭代数组中的所有元素。
本章讨论如下内容:
●简单数组
●多维数组
●锯齿数组
●Array类
●数组的接口
●枚举
5.1 简单数组
如果需要使用同一类型的多个对象,就可以使用数组。数组是一种数据结构,可以包含同一类型的多个元
素。
5.1.1 数组的声明
在声明数组时,应先定义数组中元素的类型,其后是一个空方括号和一个变量名。例如,下面声明了一个
包含整型元素的数组:
int[] myArray;
typeof array5.1.2 数组的初始化
声明了数组后,就必须为数组分配内存,以保存数组的所有元素。数组是引用类型,所以必须给它分配堆
上的内存。为此,应使用new运算符,指定数组中元素的类型和数量来初始化数组的变量。下面指定了数组
的大小。
第5章数组提示:值类型和引用类型请参见第3章。
myArray = new int[4];
,如图5-1所示。
在声明和初始化
警告:在指定了数组的大小后,如果不复制数组中的所有元素,就不能重新设置数组的大小。如果事先不知道数组中应包含多少个元素,就可以使用集合。集合请参见第10章。
除了在两个语句中声明和初始化数组之外,还可以在一个语句中声明和初始化数组:
int[] myArray = new int[4];
还可以使用数组初始化器为数组的每个元素赋值。数组初始化器只能在声明数组变量时使用,不能在声明数组之后使用。
int[] myArray = new int[4] {4, 7, 11, 2};
如果用花括号初始化数组,还可以不指定数组的大小,因为编译器会计算出元素的个数:
int[] myArray = new int[] {4, 7, 11, 2};
使用C# 编译器还有一种更简化的形式。使用花括号可以同时声明和初始化数组,编译器生成的代码与前面的例子相同:
int[] myArray = {4, 7, 11, 2};
5.1.3 访问数组元素
数组在声明和初始化后,就可以使用索引器访问其中的元素了。数组只支持有整型参数的索引器。
提示:在定制的类中,可以创建支持其他类型的索引器。创建定制索引器的内容请参见第6章。
通过索引器传送元素号,就可以访问数组。索引器总是以0开头,表示第一个元素。可以传送给索引器的最大值是元素个数减1,因为索引从0开始。在下面的例子中,数组myArray用4个整型值声明和初始化。用索引器0、1、2、3就可以访问该数组中的元素。
int[] myArray = new int[] {4, 7, 11, 2};
int v1 = myArray[0]; // read first element
int v2 = myArray[1]; // read second element
myArray[3] = 44; // change fourth element
警告:如果使用错误的索引器值(不存在对应的元素),就会抛出IndexOutOfRangeException类型的异常。
如果不知道数组中的元素个数,则可以在for语句中使用Length属性:
for (int i = 0; i < myArray.Length; i++)
{
Console.WriteLine(myArray[i]);
}
第5章 数组
除了使用for 语句迭代数组中的所有元素之外,还可以使用foreach 语句:
for (int val in myArray)
{
Console.WriteLine(val); }
提示:foreach 语句利用了本章后面讨论的IEnumerable 和IEnumerator 接口。
5.1.4 使用引用类型
不但能声明预定义类型的数组,还可以声明定制类型的数组。下面用Person 类来说明,这个类有两个构造函数、自动实现的属性Firstname 和Lastname 、以及ToString()方法的一个重写:
public class Person {
public Person() { }
public Person(string firstName, string lastName) {
this. firstname = firstName;
this.lastname = lastName; }
public string Firstname{ get; set; } public string Lastname{ get; set; } public override string ToString() {
return String.Format("{0} {1}", firstName, lastName); } }
声明一个包含两个Person 元素的数组,与声明一个int 数组类似:
Person[] myPersons = new Person[2];
但是必须注意,如果数组中的元素是引用类型,就必须为每个数组元素分配内存。若使用了数组中未分配内存的元素,就会抛出NullReferenceException 类型的异常。
提示:第14章介绍了错误和异常的详细内容。
使用从0开始的索引器,可以为数组的每个元素分配内存: myPersons [0] = new Person("Ayrton", "Senna");
myPersons [1] = new Person("Michael", "Schumacher");
图5-2显示了Person 数组中的对象在托管堆中的情况。myPersons 是一个存储在堆栈上的变量,该变量引用了存储在托管堆上的Person 元素数组。这个数组有足够容纳两个引用的空间。数组中的每一项都引用了一个Person 对象,而这些Person 对象也存储
在托管堆上。
图 5-2
it's wrong Edited by Foxit Reader
Copyright(C) by Foxit Corporation,2005-2010For Evaluation Only.
与int类型一样,也可以对定制类型使用数组初始化器:
Person[] myPersons = {new Person("Ayrton", "Senna"),
new Person("Michael", "Schumacher") };
5.2 多维数组
一般数组(也称为一维数组)用一个整数来索引。多维数组用两个或多个整数来索引。
图5-3是二维数组的数学记号,该数组有三行三列。第一行的值是1、2和3,第三行的值是7、8和9。
图5-3
在C# 中声明这个二维数组,需要在括号中加上一个逗号。数组在初始化时应指定每一维的大小(也称为阶)。接着,就可以使用两个整数作为索引器,来访问数组中的元素了:
int[,] twodim = new int[3, 3];
twodim[0,0] = 1;
twodim[0,1] = 2;
twodim[0,2] = 3;
twodim[1,0] = 4;
twodim[1,1] = 5;
twodim[1,2] = 6;
twodim[2,0] = 7;
twodim[2,1] = 8;
twodim[2,2] = 9;
提示:数组声明之后,就不能修改其阶数了。
如果事先知道元素的值,也可以使用数组索引器来初始化二维数组。在初始化数组时,使用一个外层的花括号,每一行用包含在外层花括号中的内层花括号来初始化。
int[,] twodim = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, };
提示:使用数组初始化器时,必须初始化数组的每个元素,不能遗漏任何元素。
在花括号中使用两个逗号,就可以声明一个三维数组:
int[,,] threedim = { { {1, 2}, {3, 4} }, { {5, 6}, {7, 8} }, { {9, 10}, {11, 12} }, };
Console.WriteLine(threedim[0,1,1]);
5.3 锯齿数组
二维数组的大小是矩形的,例如3×3个元素。而锯齿数组的大小设置是比较灵活的,在锯齿数组中,每一行都可以有不同的大小。
图5-4比较了有3×3个元素的二维数组和锯齿数组。图中的锯齿数组有3行,第一行有2个元素,第二行有6个元素,第三行有3个元素。
图5-4
在声明锯齿数组时,要依次放置开闭括号。在初始化锯齿数组时,先设置该数组包含的行数。定义各行中元素个数的第二个括号设置为空,因为这类数组的每一行包含不同的元素数。之后,为每一行指定行中的元素个数:
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};
迭代锯齿数组中所有元素的代码可以放在嵌套的for循环中。在外层的for循环中,迭代每一行,内层的for循环迭代一行中的每个元素:
for ( int row = 0; row < jagged.Length; row++)
{
for ( int element = 0; element <jagged[row].Length; element++)
{
Console.WriteLine("row: {0}, element: [1], value: {2}",
row, element, <jagged[row].[element]);
}
}
该迭代显示了所有的行和每一行中的各个元素:
row: 0, element: 0, value: 1
row: 0, element: 1, value: 2
row: 1, element: 0, value: 3
row: 1, element: 1, value: 4
row: 1, element: 2, value: 5
row: 1, element: 3, value: 6
row: 1, element: 4, value: 7
row: 1, element: 5, value: 8
row: 2, element: 1, value: 9
row: 2, element: 2, value: 10
row: 2, element: 3, value: 11
5.4 Array类
用括号声明数组是C# 中使用Array类的记号。在后台使用C# 语法,会创建一个派生于抽象基类Array 的新类。这样,就可以使用Array类为每个C# 数组定义的方法和属性了。例如,前面就使用了Length属性,还使用foreach语句迭代数组。其实这是使用了Array类中的GetEnumerator()方法。
5.4.1 属性
Array类包含的如下属性可以用于每个数组实例。本章后面还将讨论其他更多的属性。
第5章 数组
表5-1
属 性
说 明
Length
Length 属性返回数组中的元素个数。如果是一个多维数组,该属性会返回
所有阶的元素个数。如果需要确定一维中的元素个数,则可以使用GetLength()方法
LongLength
Length 属性返回int 值,而LongLength 属性返回long 值。如果数组包含的
元素个数超出了32位int 值的取值范围,就需要使用LongLength 属性,来获得元素个数
Rank
与 Compare 一样,但不考虑文化背景
5.4.2 创建数组
Array 类是一个抽象类,所以不能使用构造函数来创建数组。但除了可以使用C#语法创建数组实例之外,
还可以使用静态方法CreateInstance()创建数组。如果事先不知道元素的类型,就可以使用该静态方法,因为类型可以作为Type 对象传送给CreateInstance()方法。
下面的例子说明了如何创建类型为int 、大小为5的数组。CreateInstance()方法的第一个参数应是元素的类型,第二个参数定义数组的大小。可以用SetValue()方法设置值,用GetValue()方法读取值:
Array intArray1 = Array.CreateInstance(typeof(int), 5); for (int i = 0; i < 5; i++) {
intArray1.SetValue(33, i); }
for (int i = 0; i < 5; i++) {
Console.WriteLine(intArray1.GetValue(i)); }
还可以将已创建的数组强制转换成声明为int[]的数组:
int[] intArray2 = (int[])intArray1;
CreateInstance()方法有许多重载版本,可以创建多维数组和不基于0的数组。下面的例子就创建了一个包含2×3个元素的二维数组。第一维基于1,第二维基于0:
int[] lengths = {2, 3};
int[] lowerBounds = {1, 10};
Array racers = Array.CreateInstance(typeof(Person), lengths, lowerBounds);
SetValue()方法设置数组的元素,其参数是每一维的索引:
racers.SetValue(new Person("Alain", "Prost"), 1, 10);
racers.SetValue(new Person("Emerson", "Fittipaldi"), 1, 11); racers.SetValue(new Person("Ayrton", "Senna"), 1, 12); racers.SetValue(new Person("Ralf", "Schumacher"), 2, 10); racers.SetValue(new Person("Fernando", "Alonso"), 2, 11); racers.SetValue(new Person("Jenson", "Button"), 2, 12);
尽管数组不是基于0的,但可以用一般的C# 记号将它赋予一个变量。只需注意不要超出边界即可:
Person[,] racers2 = (Person[,]) racers; Person first = racers2[1, 10]; Person last = racers2[2, 12];
本页已使用福昕阅读器进行编辑。福昕软件(C)2005-2007,版权所有,仅供试用。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论