C#高级编程(第10版) C# 6 & .NET Core 1.0 (.NET开发经典名著)
上QQ阅读APP看书,第一时间看更新

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>访问。如果数组段中的元素改变了,这些变化就会反映到原数组中。