2) Массивы и стандартные коллекции .NET / Конфигурация .NET приложений

Массивы и класс System.Array
Класс System. Array является базовым классом для любого массива. Любой массив реализует интерфейсы IStructuralEquatable, IStructuralComparable, IList и IList<T> , причём первые три интерфейса реализованы явно (методы Add() и Remove() генерируют исключение в случае коллекции фиксированной длины, которой является массив).


Типы для работы с коллекциями-списками
Класс List <T> из пространства имён System.Collections.Generic – основной класс для представления наборов, которые допускают динамическое добавление элементов. Для хранения данных набора используется внутренний массив. Класс List<T> реализует интерфейсы IList<T>, IList, IReadOnlyList<T>.
Класс List<T> имеет три конструктора. Первый из них – обычный конструктор без параметров. Второй конструктор позволяет создать набор на основе коллекции – производится копирование элементов коллекции в список. Третий конструктор принимает в качестве аргумента начальную ёмкость набора. Ёмкость набора (capacity) – это количество элементов набора, которое он способен содержать без увеличения размера внутреннего массива.
На примере List<T> рассмотрим особенность, присущую использованию коллекций в языке C#. Если коллекция хранит структуры, то C# не позволяет изменить части структуры при помощи индексатора коллекции (так как индексатор является функцией, возвращающей копию элемента коллекции).
Класс LinkedList <T> служит для представления двусвязного списка. Такой список позволяет осуществлять вставку и удаление элемента без сдвига остальных элементов. Однако доступ к элементу по индексу требует прохода по списку. LinkedList <T> реализует интерфейсы ICollection и ICollection<T>. Каждый элемент двусвязного списка представлен объектом LinkedListNode<T>.
При добавлении элемента можно указать, чтобы он помещался в начало списка, или в конец списка, или относительно существующего в списке элемента. (addfirst,addlast,addafter)
Класс LinkedList <T> содержит свойства для числа элементов, для указания на первый и последний элемент. Имеются методы для поиска элементов.
Классы Queue <T> и Stack <T> реализуют структуры данных «очередь» и «стек» на основе массива. Конструкторы этих классов, как и конструкторы класса List <T>, позволяют создать объект на основе другой коллекции, а также указать значение для ёмкости (но ёмкость не доступна в виде отдельного свойства).

Типы для работы с коллекциями-множествами
В библиотеке базовых классов платформы .NET имеются два класса для представления множеств (то есть коллекций, которые не содержат повторяющихся элементов) – HashSet<T> и SortedSet<T> . Оба класса реализуют интерфейс ISet<T> .
Класс HashSet <T> описывает множество, в котором вхождение элемента проверяется на основе хэш-кода. Конструкторы класса HashSet<T> позволяют создать множество на основе коллекции, а также указать объект, реализующий интерфейс IEqualityComparer <T> для проверки равенства элементов множества. Кроме реализации интерфейса ISet<T> , класс HashSet<T> содержит экземплярный метод RemoveWhere() для удаления элементов, удовлетворяющих заданному предикату. Статический метод CreateSetComparer() возвращает экземпляр класса, реализующего IEqualityComparer<HashSet <T>>.
Класс SortedSet <T> – это множество, поддерживающее набор элементов в отсортированном порядке.
Набор методов SortedSet<T> схож с набором методов класса HashSet<T> . Экземплярный метод Reverse() возвращает набор элементов в противоположном порядке, а метод GetViewBetween() возвращает фрагмент («окно») исходного множества между двумя элементами.

Типы для работы с коллекциями-словарями
Под термином словарь будем понимать коллекцию, которая хранит пары «ключ-значение» с возможностью доступа к элементам по ключу.
Универсальный класс Dictionary<TKey, TValue> – классический словарь с возможностью указать тип для ключа и тип для значения. Класс Dictionary<TKey, TValue> реализует обе версии интерфейса IDictionary (обычную и универсальную).
Класс OrderedDictionary – слаботипизированный класс, запоминающий порядок добавления элементов в словарь. В некотором смысле, данный класс является комбинацией классов Hashtable и ArrayList . Для доступа к элементам в OrderedDictionary можно применять как ключ, так и целочисленный индекс.
Класс ListDictionary использует для хранения элементов словаря не хэш-таблицу, а односвязный список. Это делает данный класс неэффективным при работе с большими наборами данных. ListDictionary рекомендуется использовать, если количество хранимых элементов не превышает десяти. Класс HybridDictionary – это форма словаря, использующая список для хранения при малом количестве элементов, и переключающаяся на применение хэш-функции, когда количество элементов превышает определённый порог. Оба класса ListDictionary и HybridDictionary являются слаботипизированными и находятся в пространстве имён System.Collections.Specialized.
Платформа .NET предоставляет три класса-словаря, организованных так, что их элементы всегда отсортированы по ключу: SortedDictionary<TKey, TValue>, SortedList и SortedList <TKey, TValue>. Данные классы используют разные внутренние структуры для хранения элементов словаря. Класс SortedDictionary<TKey, TValue> быстрее классов SortedList и SortedList <TKey, TValue> при выполнении вставки элементов. Но классы SortedList и SortedList<TKey, TValue> могут предоставить возможность, которой нет у SortedDictionary<TKey, TValue> – доступ к элементу не только по ключу, но и с использованием целочисленного индекса.

Файлы конфигурации
Конфигурирование применяется для решения двух основных задач. Во-первых, параметры конфигурации позволяют настроить поведение CLR при выполнении кода приложения. Во-вторых, конфигурация может хранить пользовательские данные приложения.
Платформа .NET предлагает унифицированный подход к конфигурированию, основанный на использовании конфигурационных XML-файлов .
Платформа .NET предлагает унифицированный подход к конфигурированию, основанный на использовании конфигурационных XML-файлов . Существует один глобальный файл конфигурации с параметрами, относящимися к платформе в целом. Этот файл называется machine.config и располагается в каталоге установки платформы .NET. Любая сборка может иметь локальный конфигурационный файл. Он должен носить имя файла сборки с добавлением расширения .config и располагаться в одном каталоге со сборкой (то есть файл конфигурации для main.exe должен называться main.exe.config1). Параметры, описанные в локальных конфигурационных файлах, «накладываются» на параметры из файла machine.config.
Проанализируем общую схему любого файла конфигурации. Корневым XML-элементом файла является элемент <configuration >. Он может включать следующие дочерние элементы:
<configSections > – описывает разделы конфигурации (в том числе пользовательские);
<appSettings > – пользовательские параметры конфигурации;
<connectionStrings > – строки подключения к источникам данных;
<startup > – параметры запуска CLR (поддерживаемые версии);
<runtime > – параметры времени выполнения (регулируют способ загрузки сборок и работу сборщика мусора);
<system.diagnostics > – совокупность диагностических параметров, которые задают способ отладки, перенаправляют сообщения отладки и т. д.;
<system.net > – настройка параметров работы с сетью;
<system.serviceModel > – настройка элементов технологии WCF;
<system.web > – параметры конфигурации приложений ASP.NET.
Рассмотрим способы описания в файле конфигурации пользовательских данных. В простейшем случае для этого используется раздел <appSettings >, который может содержать следующие элементы:
<add key ="name" value="the value"/> – добавляет новый ключ и значение в коллекцию пользовательских конфигурационных данных;
<remove key ="name"/> – удаляет существующий ключ и значение из коллекции конфигурационных данных;
<clear/> – очищает коллекцию конфигурационных данных.
Разработчик может создать собственный раздел конфигурационного файла. Такой раздел должен быть зарегистрирован в секции <configSections>. При регистрации раздела задаётся его обработчик – класс, который будет отвечать за превращение содержимого раздела в данные. В зависимости от типа хранимых данных можно воспользоваться одним из существующих обработчиков либо построить собственный обработчик.
 Для программного доступа к конфигурационным данным текущего приложения используется статический класс ConfigurationManager из пространства имён System.Configuration1 (сборка System.Configuration.dll). Класс имеет следующие элементы:
1. AppSettings – коллекция-словарь пользовательских параметров;
2. ConnectionStrings – словарь строк подключения к источникам данных;
3. GetSection() – извлекает указанный раздел конфигурации;
4. OpenExeConfiguration() – открывает файл конфигурации указанной сборки в виде объекта Configuration;
5. OpenMachineConfiguration() – открывает файл machine.config;
6. RefreshSection() – перечитывает указанный раздел конфигурации.
При работе в Visual Studio можно создать так называемые пользовательские настройки . Для этого используется окно свойств проекта (Project | Properties | Settings). Для каждого параметра указывается имя, тип и область видимости – глобальная или локальная (для конкретного пользователя).