Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSharp Language Specification.doc
Скачиваний:
13
Добавлен:
26.09.2019
Размер:
4.75 Mб
Скачать

10.6.1.4Массивы параметров

Параметр, объявленный с модификатором params, является массивом параметров. Если список формальных параметров включает массив параметров, тот должен быть последним параметром в списке и должен иметь тип одномерного массива. Например, типы string[] и string[][] могут использоваться в качестве типа массива параметров, но тип string[,] – не может. Невозможно объединить модификатор params с модификаторами ref и out.

Массив параметров позволяет указывать аргументы одним из двух способов при вызове метода:

  • Аргумент, заданный для массива параметров, может быть единственным выражением, неявно преобразуемым (§6.1) в тип массива параметров. В таком случае массив параметров действует точно так же, как параметр по значению;

  • Либо в вызове могут быть заданы нуль или несколько аргументов для массива параметров, где каждый аргумент является выражением, неявно преобразуемым (§6.1) в тип элемента массива параметров. В таком случае вызов создает экземпляр типа массива параметров с длиной, соответствующей числу аргументов, инициализирует элементы экземпляра массива заданными значениями аргументов и использует вновь созданный экземпляр массива в качестве фактического аргумента.

Кроме разрешения переменного числа аргументов при вызове, массив параметров совершенно эквивалентен параметру по значению (§10.6.1.1) того же типа.

Пример.

using System;

class Test { static void F(params int[] args) { Console.Write("Array contains {0} elements:", args.Length); foreach (int i in args) Console.Write(" {0}", i); Console.WriteLine(); }

static void Main() { int[] arr = {1, 2, 3}; F(arr); F(10, 20, 30, 40); F(); } }

В этом примере производятся следующие выходные данные

Array contains 3 elements: 1 2 3 Array contains 4 elements: 10 20 30 40 Array contains 0 elements:

При первом вызове F просто передает массив a в качестве параметра по значению. При втором вызове F автоматически создает четырехэлементный массив int[] с заданными значениями элементов и передает этот массив в качестве параметра по значению. Аналогично, третий вызов F создает массив из нуля элементов int[] и передает этот экземпляр в качестве параметра по значению. Второй и третий вызовы полностью эквивалентны следующему коду:

F(new int[] {10, 20, 30, 40}); F(new int[] {});

При выполнении разрешения перегрузки метод с массивом параметров может применяться либо в его обычном виде, либо в расширенном виде (§7.5.3.1). Расширенный вид метода доступен, если только неприменим обычный вид, и если только в том же типе уже не объявлен метод с такой же сигнатурой, как у расширенного вида.

Пример.

using System;

class Test { static void F(params object[] a) { Console.WriteLine("F(object[])"); }

static void F() { Console.WriteLine("F()"); }

static void F(object a0, object a1) { Console.WriteLine("F(object,object)"); }

static void Main() { F(); F(1); F(1, 2); F(1, 2, 3); F(1, 2, 3, 4); } }

В этом примере производятся следующие выходные данные

F(); F(object[]); F(object,object); F(object[]); F(object[]);

В этом примере два из возможных расширенных видов метода с массивом параметров уже включены в класс как обычные методы. Поэтому эти расширенные виды не рассматриваются при выполнении разрешения перегрузки, а первый и третий вызовы метода таким образом выбирают обычные методы. Если в классе объявляют метод с массивом параметров, нередко включают и некоторые из расширенных видов в качестве обычных методов. При этом становится возможным избежать выделения экземпляра массива, которое происходит при вызове расширенного вида метода с массивом параметров.

Если массив параметров имеет тип object[], возникает потенциальная неоднозначность между нормальной и расширенной формами метода для одного параметра типа object. Причиной неоднозначности является то, что object [] сам может неявно преобразовываться в тип object. Неоднозначность не ведет к возникновению проблем и при необходимости может быть разрешена с помощью приведения.

Пример.

using System;

class Test { static void F(params object[] args) { foreach (object o in args) { Console.Write(o.GetType().FullName); Console.Write(" "); } Console.WriteLine(); }

static void Main() { object[] a = {1, "Hello", 123.456}; object o = a; F(a); F((object)a); F(o); F((object[])o); } }

В этом примере производятся следующие выходные данные

System.Int32 System.String System.Double System.Object[] System.Object[] System.Int32 System.String System.Double

При первом и последнем вызове функции F применима нормальная форма F, поскольку существует неявное преобразование из типа аргумента к типу параметра (оба имеют тип object[]). Таким образом, в результате разрешения перегрузки выбирается нормальная форма F, а аргумент передается как регулярный параметр значения. Во втором и в третье вызовах обычная форма F неприменима, поскольку не существует неявного преобразования из типа аргумента в тип параметра (тип object не может быть неявно преобразован в тип object[]). Однако в этом случае применима расширенная форма F, которая выбирается в результате разрешения перегрузки. В результате вызовом создается одноэлементный массив object[], и единственный элемент массива инициализируется данным значением аргумента (который сам является ссылкой на object[]).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]