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

7.6.10.3Инициализаторы коллекции

Инициализатор коллекции задает элементы коллекции.

инициализатор_коллекции: { список_инициализаторов_элементов } { список_инициализаторов_элементов , }

список_инициализаторов_элементов: инициализатор_элемента список_инициализаторов_элементов , инициализатор_элемента

инициализатор_элемента: выражение_не_присваивания { список_выражений }

список_выражений: выражение список_выражений , выражение

Инициализатор коллекции состоит из последовательности инициализаторов элементов, заключенных между лексемами { и } и разделенных запятыми. Каждый инициализатор элемента задает элемент, добавляемый в инициализируемый объект коллекции, и состоит из списка выражений, заключенных между лексемами { и } и разделенных запятыми. Инициализатор элемента с одним выражением можно записывать без скобок, но в таком случае оно не может быть выражением присваивания, чтобы избежать неоднозначности с инициализаторами членов. Создание выражения_не_присваивания определяется в разделе §7.18.

Ниже приводится пример выражения создания объекта, в которое входит инициализатор коллекции:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Объект коллекции, к которому применяется инициализатор коллекции, должен иметь тип, в котором реализуется интерфейс System.Collections.Ienumerable, иначе будет возникать ошибка времени компиляции. Для каждого указанного элемента по порядку инициализатор вызывает метод Add целевого объекта со списком выражений инициализатора элемента в качестве списка аргументов, применяя обычное разрешение перегрузки для каждого вызова. Таким образом, объект коллекции должен содержать применимый метод Add для каждого инициализатора элемента.

Следующий класс представляет собой контакт с именем и списком телефонных номеров:

public class Contact { string name; List<string> phoneNumbers = new List<string>();

public string Name { get { return name; } set { name = value; } }

public List<string> PhoneNumbers { get { return phoneNumbers; } } }

Экземпляр List<Contact> можно создать и инициализировать следующим образом:

var contacts = new List<Contact> { new Contact { Name = "Chris Smith", PhoneNumbers = { "206-555-0101", "425-882-8080" } }, new Contact { Name = "Bob Harris", PhoneNumbers = { "650-555-0199" } } };

что равносильно

var __clist = new List<Contact>(); Contact __c1 = new Contact(); __c1.Name = "Chris Smith"; __c1.PhoneNumbers.Add("206-555-0101"); __c1.PhoneNumbers.Add("425-882-8080"); __clist.Add(__c1); Contact __c2 = new Contact(); __c2.Name = "Bob Harris"; __c2.PhoneNumbers.Add("650-555-0199"); __clist.Add(__c2); var contacts = __clist;

где __clist, __C1 и __c2 являются временными переменными, не видимыми и недоступными другим образом.

7.6.10.4Выражения создания массива

Выражение_создания_массива используется для создания нового экземпляра типа_массива.

выражение_создания_массива: тип_не_массива [ список_выражений ] спецификации_ранганеобязательно инициализатор_массиванеобязательно new тип_массива инициализатор_массива new спецификация_ранга инициализатор_массива

Выражение создания массива первого типа создает экземпляр массива с типом, который получается после удаления всех отдельных выражений из списка выражений. Например, выражение создания массива new int[10, 20] создает экземпляр массива с типом int[,], а выражение new int[10][,] — экземпляр массива с типом int[][,]. Каждое выражение в списке выражений должно иметь тип int, uint, long или ulong или тип, который может быть явно преобразован в один или несколько этих типов. Значение каждого выражения определяет размер соответствующего измерения в новом созданном экземпляре массива. Поскольку размер измерения массива должен быть неотрицательным, при наличии константного_выражения с отрицательным значением в списке выражений будет возникать ошибка времени компиляции.

За исключением небезопасных контекстов (§18.1) формат массива не указывается.

Если выражение создания массива первого типа содержит инициализатор массива, то каждое выражение в списке выражений должно быть константным, а ранг и длина измерения, указанные в списке выражений, должны совпадать с соответствующими значениями инициализатора массива.

В выражении создания массива второго или третьего типа ранг указанного типа массива или спецификация ранга должны быть равны соответствующим значениям инициализатора массива. Длины отдельных измерений выводятся из числа элементов в каждом соответствующем вложенном уровне инициализатора массива. Таким образом, выражение

new int[,] {{0, 1}, {2, 3}, {4, 5}}

в точности соответствует

new int[3, 2] {{0, 1}, {2, 3}, {4, 5}}

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

Инициализаторы массива подробнее описываются далее в разделе §12.6.

Результат вычисления выражения создания массива классифицируется как значение, а именно как ссылка на новый созданный экземпляр массива. Во время выполнения обработка выражения создания массива включает следующие этапы.

  • Вычисляются выражения длины измерений в списке_выражений по порядку слева направо. После вычисления всех выражений выполняется неявное преобразование (§6.1) в один из следующих типов: Выбирается первый тип из этого списка, для которого существует неявное преобразование. Если при вычислении выражения или последующем неявном преобразовании возникает исключение, то следующие выражения не вычисляются и дальнейшие этапы не выполняются.

  • Вычисленные значения для длин измерений проверяются следующим образом. Если одно или несколько значений оказываются меньше нуля, то вызывается исключение System.OverflowException и дальнейшие этапы не выполняются.

  • Создается экземпляр массива с полученными длинами измерений. Если для создания нового экземпляра недостаточно памяти, то возникает исключение System.OutOfMemoryException и дальнейшие этапы не выполняются

  • Все элементы нового экземпляра массива инициализируются с помощью значений по умолчанию (§5.2).

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

Выражение создания массива позволяет проводить инициализацию массива с помощью элементов типа массива, однако элементы такого массива необходимо инициализировать вручную. Например, в выражении

int[][] a = new int[100][];

создается одномерный массив со 100 элементами типа int[]. Исходным значением каждого элемента является null. В этом же выражении создания массива нельзя инициализировать подмассивы, и выражение

int[][] a = new int[100][5]; // Error

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

int[][] a = new int[100][]; for (int i = 0; i < 100; i++) a[i] = new int[5];

Когда массив массивов имеет «прямоугольную» форму, то есть когда все подмассивы имеют одинаковую длину, более эффективно использовать многомерный массив. В примере выше при инициализации массива массивов создается 101 объект — один внешний массив и 100 вложенных массивов. Напротив, в выражении

int[,] = new int[100, 5];

создается только один объект, двумерный массив, и это создание выполняется в одном выражении.

Ниже приведены примеры выражений создания массивов с неявным заданием типа.

var a = new[] { 1, 10, 100, 1000 }; // int[]

var b = new[] { 1, 1.5, 2, 2.5 }; // double[]

var c = new[,] { { "hello", null }, { "world", "!" } }; // string[,]

var d = new[] { 1, "one", 2, "two" }; // Error

Последнее выражение вызывает ошибку времени выполнения, поскольку типы int и string не могут быть неявно преобразованы один в другой, поэтому в данном случае наиболее общий тип отсутствует. В этом случае необходимо использовать выражение создания массива с явным заданием типа, например, указав тип object[]. Иначе один из элементов можно привести к общему базовому типу, который затем станет выведенным типом элемента.

Выражения создания массива с неявным заданием типа можно комбинировать с инициализаторами анонимных объектов (§7.6.10.6) для создания структуры данных с анонимным типом. Например:

var contacts = new[] { new { Name = "Chris Smith", PhoneNumbers = new[] { "206-555-0101", "425-882-8080" } }, new { Name = "Bob Harris", PhoneNumbers = new[] { "650-555-0199" } } };

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