参数数组
前面所述的参数类型都必须严格地一个实参对应一个形参。参数数组则不同,它允许零个或多个实参对应一个特殊的形参。
参数数组的重点如下:
- 在一个参数列表中只能有一个参数数组。
- 如果有,它必须是列表中的最后一个。
- 由参数数组表示的所有参数都必须具有相同的类型。
声明一个参数数组必须做的事如下:
- 在数据类型前使用 params修饰符。
- 在数据类型后放置一组空的方括号。
下面的方法头展示了int型参数数组的声明语法。在这个示例中,形参 invasi可以代表零个或多个int实参。
void ListInts( params int[] inVals )
类型名后面的空方括号指明了参数是一个整数数组。我们需要了解的内容如下:
- 数组是一组整齐的相同类型的数据项。
- 数组使用一个数字索引进行访问。
- 数组是一个引用类型,因此它的所有数据项都保存在堆中。
方法调用
可以使用两种方式为参数数组提供实参:
- 一个逗号分隔的该数据类型元素的列表。所有元素必须是方法声明中指定的类型。
ListInts( 10, 20, 30 ); //3个int
- 一个该数据类型元素的一维数组。
int[] intArray = {1,2,3};
ListInts( intArray ); //一个数组变量
请注意,在这些示例中,没有在调用时使用 params修饰符。参数数组中修饰符的使用与其他参数类型的模式并不相符。
- 其他参数类型是一致的,要么都使用修饰符,要么都不使用修饰符。
值参数的声明和调用都不带修饰符。
引用参数和输出参数在两个地方都需要修饰符。 - params修饰符的用法总结如下
在声明中需要修饰符。
在调用中不允许有修饰符。
延伸式:
参数数组方法调用的第一种形式有时被称为延仲式,这种形式在调用中使用分离的实参。
例如,下面代码中的方法 ListInts的声明可以匹配它下面所有的方法调用,虽然它们有不同数目的实参。
void ListInts( params int[] inVals ) {......(方法体)} //方法声明
ListInts(); //0实参
ListInts( 1, 2, 3); //3实参
ListInts( 4, 5, 6, 7); //4实参
ListInts( 8, 9, 10, 11, 12); //5实参
在使用一个为参数数组分离实参的调用时,编译器做下面的事:
- 接受实参列表,用它们在堆中创建并初始化一个数组。
- 把数组的引用保存到栈中的形参里。
- 如果在对应的形参数组的位置没有实参,编译器会创建一个有零个元素的数组来使用。
例如,下面的代码声明了一个名称为 ListIntsl的方法,它带有一个参数数组。Main声明了3个整数并把它们传给了数组。
class Program
{
static void Main(string[] args)
{
int first = 5, second = 6, third = 7;//声明3个int
MyClass mc = new MyClass();
mc.ListInts(first, second, third);//传入实参调用方法
Console.WriteLine("{0},{1},{2}", first, second, third);
}
}
class MyClass
{
public void ListInts(params int[] inVals) //参数数组
{
if ((inVals != null) && (inVals.Length != 0))
{
for (int i = 0; i < inVals.Length; i++) //处理数组
{
inVals[i] = inVals[i] * 10;
Console.WriteLine("{0}", inVals[i]); //显示新值
}
}
}
}
这段代码产生如下输出:
50
60
70
5,6,7
下图阐明了在方法执行的不同阶段实参和形参的值:
- 方法调用之前,3个实参已经在栈里。
- 在方法的开始,3个实参被用于初始化堆中的数组,并且数组的引用被赋值给形参inVals。
- 在方法内部,代码首先检查以确认数组引用不是null,然后处理数组,把每个元素乘以10并保存回去。
- 方法执行之后,形参 inVals失效。
关于参数数组,需要记住的重要一点是当数组在堆中被创建时,实参的值被复制到数组中。在这方面,它们像值参数。
- 如果数组参数是值类型,那么值被复制,实参不受方法内部的影响。
- 如果数组参数是引用类型,那么引用被复制,实参引用的对象可以受到方法内部的影响。
用数组作为实参
也可以在方法调用之前创建并组装一个数组,把单一的数组变量作为实参传递。这种情况下编译器使用你的数组而不是重新创建一个。
例如,下面代码使用前一个示例中声明的方法 ListInts。在这段代码中,Main创建一个数组,并用数组变量而不是使用分离的整数作为实参。
class Program
{
static void Main(string[] args)
{
int[] myArr = new int[] { 5, 6, 7 };//创建并初始化数组
MyClass mc = new MyClass();
mc.ListInts(myArr);//调用方法
foreach (int x in myArr)
{
Console.WriteLine("{0}", x);
}
}
}
class MyClass
{
public void ListInts(params int[] inVals)
{
if ((inVals != null) && (inVals.Length != 0))
{
for (int i = 0; i < inVals.Length; i++) //处理数组
{
inVals[i] = inVals[i] * 10;
Console.WriteLine("{0}", inVals[i]); //显示新值
}
}
}
}
这段代码产生如下输出:
50
60
70
50
60
70