7.6 数组作为参数
数组可以作为参数传递给方法,也可以从方法返回。要返回一个数组,只需要把数组声明为返回类型,如下面的方法GetPersons()所示:
static Person[] GetPersons() { return new Person[] { new Person { FirstName="Damon", LastName="Hill" }, new Person { FirstName="Niki", LastName="Lauda" }, new Person { FirstName="Ayrton", LastName="Senna" }, new Person { FirstName="Graham", LastName="Hill" } }; }
要把数组传递给方法,应把数组声明为参数,如下面的DisplayPersons()方法所示:
static void DisplayPersons(Person[] persons) { //...
7.6.1 数组协变
数组支持协变。这表示数组可以声明为基类,其派生类型的元素可以赋予数组元素。
例如,可以声明一个object[]类型的参数,给它传递一个Person[]:
static void DisplayArray(object[] data) { //… }
注意:数组协变只能用于引用类型,不能用于值类型。另外,数组协变有一个问题,它只能通过运行时异常来解决。如果把Person数组赋予object数组,object数组就可以使用派生自object的任何元素。例如,编译器允许把字符串传递给数组元素。但因为object数组引用Person数组,所以会出现一个运行时异常ArrayTypeMismatchException。
7.6.2 ArraySegment<T>
结构ArraySegment<T>表示数组的一段。如果需要使用不同的方法处理某个大型数组的不同部分,那么可以把相应的数组部分复制到各个方法中。此时,与创建多个数组相比,更有效的方法是使用一个数组,将整个数组传递给不同的方法。这些方法只使用数组的某个部分。方法的参数除了数组以外,还应包括数组内的偏移量以及该方法应该使用的元素数。这样一来,方法就需要至少3个参数。当使用数组段时,只需要一个参数就可以了。ArraySegment<T>结构包含了关于数组段的信息(偏移量和元素个数)。
SumOfSegments()方法提取一组ArraySegment<int>元素,计算该数组段定义的所有整数之和,并返回整数和(代码文件ArraySegmentSample/Program.cs):
static int SumOfSegments(ArraySegment<int>[] segments) { int sum = 0; foreach (var segment in segments) { for (int i = segment.Offset; i < segment.Offset + segment.Count; i++) { sum += segment.Array[i]; } } return sum; }
使用这个方法时,传递了一个数组段。第一个数组元素从ar1的第一个元素开始,引用了3个元素;第二个数组元素从ar2的第4个元素开始,引用了3个元素;
int[] ar1 = { 1, 4, 5, 11, 13, 18 }; int[] ar2 = { 3, 4, 5, 18, 21, 27, 33 }; var segments = new ArraySegment<int>[2] { new ArraySegment<int>(ar1, 0, 3), new ArraySegment<int>(ar2, 3, 3) }; var sum = SumOfSegments(segments);
注意:数组段不复制原数组的元素,但原数组可以通过ArraySegment<T>访问。如果数组段中的元素改变了,这些变化就会反映到原数组中。