在迄今为止讲到的例子中,参数数量都由方法声明进行了固定。然而,我们有时希望参数的数量是可变的。以代码清单4-11的Combine()方法为例。在那个方法中,传递了驱动器号、文件夹路径以及文件名(driveLetter、folderPath、fileName)等参数。假如路径中的文件夹数量大于1,调用者希望将额外的文件夹联结起来,以构成一个完整的路径,那么应该如何编写代码呢?也许最好的办法就是为文件夹传递一个字符串数组。然而,这会使调用代码变得稍微复杂一些,因为需要事先构造好一个数组,再将这个数组作为参数来传递。
为了简化编码,C#提供了一个特殊的关键字,它允许在调用一个方法时提供数量可变的参数,而不是由方法事先固定好参数的数量。在具体讨论这种方法声明之前,先观察一下代码清单4-14的Main()方法中的调用代码。
代码清单4-14 传递一个长度可变的参数列表
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ParamsTest
{
class Program
{
static string Combine(params string[] paths)
{
string result = string.Empty;
foreach (string path in paths)
{
result = System.IO.Path.Combine(result, path);
}
return result;
}
static void Main(string[] args)
{
string fullName;
// ...
// Call Combine() with four parameters
fullName = Combine(Directory.GetCurrentDirectory(), "bin", "config", "index.html");
Console.WriteLine(fullName);
// ...
// Call Combine() with only three parameters
fullName = Combine(Environment.SystemDirectory, "Temp", "index.html");
Console.WriteLine(fullName);
// ...
// Call Combine() with an array
fullName = Combine(new string [] {"C:\\","Data","HomeDir","index.html"});
Console.WriteLine(fullName);
Console.ReadKey();
// ...
}
}
}
输出4-8展示了代码清单4-14的结果。
输出4-8
C:\Data\mark\bin\config\index.html |
在第一个Combine()调用中,我们指定了4个参数。第二个调用只指定了3个参数。在最后一个调用中,参数用一个数组来传递。换言之,Combine()方法可接受数量可变的参数,不管这些参数是以逗号分隔的,还是整体作为一个数组来传递的。
为了获得这样的效果,Combine()方法需要:
(1) 在方法声明的最后一个参数之前,添加一个params关键字;
(2) 将最后一个参数声明为一个数组。
像这样声明了一个参数数组(parameter array)之后,就可以将每个参数作为参数数组的一个成员来访问了。在Combine()方法的实现中,我们遍历paths数组的每个元素,并调用System.IO. Path.Combine()。这个方法能自动合并一个路径中的各个部分,并能正确地使用平台特有的目录分隔符。注意,PathEx.Combine()完全等价于Path.Combine(),只是PathEx.Combine()能处理数量可变的参数,而非只能处理两个。
参数数组有以下一些值得注意的特征。
参数数组不一定是方法声明中的唯一参数。但是,参数数组必须是方法声明中的最后一个参数。由于只有最后一个参数才可能是参数数组,所以方法最多只能有一个参数数组。
调用者可以为参数数组指定零个参数,这会造成包含零个数据项的一个数组。
参数数组是类型安全的——类型必须匹配于数组指定的类型。
调用者可以显式地提供一个数组,而不是以逗号分隔的参数列表。最终生成的CIL代码是一样的。
假如目标方法的实现要求一个最起码的参数数量,请在方法声明中显式指定必须提供的参数。这样一来,假如要求的参数遗失了,就会强迫编译器报错,而不是依赖于运行时错误处理。例如,使用int Max(int first, params int[] operads)而不是int Max(params int[] operads),确保至少有一个值传给Max()。
使用参数数组,我们可以将相同类型的、数量可变的多个参数传给一个方法。本章后面的4.7节讨论了如何支持不同类型的、数量可变的参数。