Передача переменного количества
аргументов
Иногда разработчику удобно определить метод, способный принимать переменное
число параметров. Например, тип
System.String
предлагает методы, выполняю-
щие объединение произвольного числа строк, а также методы, при вызове которых
можно задать набор единообразно форматируемых строк.
Метод, принимающий переменное число аргументов, объявляют так:
static Int32 Add(params Int32[] values) {
// ПРИМЕЧАНИЕ: при необходимости этот массив
// можно передать другим методам
Int32 sum = 0;
if (values != null) {
for (Int32 x = 0; x < values.Length; x++)
sum += values[x];
}
return sum;
}
Незнакомым в этом методе является только ключевое слово
params
, примененное
к последнему параметру в сигнатуре метода. Если не обращать на него внимания,
станет ясно, что метод принимает массив значений типа
Int32
, складывает все
элементы этого массива и возвращает полученную сумму.
Очевидно, этот метод можно вызвать так:
public static void Main() {
// Выводит "15"
Console.WriteLine(Add(new Int32[] { 1, 2, 3, 4, 5 } ));
}
Не вызывает сомнений утверждение, что этот массив легко инициализировать
произвольным числом элементов и передать для обработки методу
Add
. Показан-
ный здесь код немного неуклюж, хотя он корректно компилируется и работает.
Разработчики, конечно, предпочли бы вызывать метод
Add
так:
public static void Main() {
// Выводит "15"
Console.WriteLine(Add(1, 2, 3, 4, 5));
}
Такая форма вызова возможна благодаря ключевому слову
params
. Именно оно
заставляет компилятор рассматривать параметр как экземпляр настраиваемого
атрибута
System.ParamArrayAttribute
.
258
Глава.9 .Параметры
Обнаружив такой вызов, компилятор C# проверяет все методы с заданным име-
нем, у которых ни один из параметров не помечен атрибутом
ParamArray
. Найдя
метод, способный принять вызов, компилятор генерирует вызывающий его код.
В противном случае ищутся методы с атрибутом
ParamArray
и проверяется, могут
ли они принять вызов. Если компилятор находит подходящий метод, то прежде чем
сгенерировать код его вызова, он генерирует код, создающий и заполняющий массив.
В предыдущем примере не определен метод
Add
, принимающий пять совмести-
мых с типом
Int32
аргументов. Компилятор же видит в тексте исходного кода вызов
метода
Add
, которому передается список значений
Int32
, и метод
Add
, у которого
массив типа
Int32
помечен атрибутом
ParamArray
. Компилятор считает данный
метод подходящим для вызова и генерирует код, собирающий все параметры в мас-
сив типа
Int32
и вызывающий метод
Add
. В конечном итоге получается, что можно
написать вызов, без труда передающий методу
Add
набор параметров, и компиля-
тор сгенерирует тот же код, что и для первой версии вызова метода
Add
, в которой
массив создается и инициализируется явно.
Ключевым словом
params
может быть помечен только последний параметр
метода (
ParamArrayAttribute
). Он должен указывать на одномерный массив про-
извольного типа. В последнем параметре метода допустимо передавать значение
null
или ссылку на массив, состоящий из нуля элементов. Следующий вызов ме-
тода
Add
прекрасно компилируется, отлично работает и дает в результате сумму,
равную 0 (как и ожидалось):
public static void Main() {
// Обе строчки выводят "0"
Console.WriteLine(Add()); // передает новый элемент Int32[0] методу Add
Console.WriteLine(Add(null)); // передает методу Add значение null,
// что более эффективно (не выделяется
}
// память под массив)
Все показанные до сих пор примеры демонстрировали методы, принимающие
произвольное количество параметров типа
Int32
. А как написать метод, принима-
ющий произвольное количество параметров любого типа? Ответ прост: достаточно
отредактировать прототип метода, заставив его вместо
Int32[]
принимать
Object[]
.
Следующий метод выводит значения
Type
всех переданных ему объектов:
public sealed class Program {
public static void Main() {
DisplayTypes(new Object(), new Random(), "Jeff", 5);
}
private static void DisplayTypes(params Object[] objects) {
if (objects != null) {
foreach (Object o in objects)
Console.WriteLine(o.GetType());
}
}
}
259
Типы.параметров.и.возвращаемых.значений
При выполнении этого кода будет выведен следующий результат:
System.Object
System.Random
System.String
System.Int32
Do'stlaringiz bilan baham: |