Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование. Введение в разработку на C#. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
В примере складываются координаты двух точек, чтобы получилась координата новой. Если мы добавим новый метод в класс Point, а в Pro- gram напишем:
Point P2d_1 = new Point(1, 2); Point P2d_2 = new Point(3, 4); Point P2d_3 = P2d_1 + P2d_2;
P2d_3.Direction();
то на консоль выведется «Координата по X = 4, Y = 6»
Все перегрузки операторов являются статическими методами класса. Кроме того, следует учесть, что если перегружается оператор равенства (==), то необходимо перегрузить и оператор неравенства (!=). Операторы < и >, а также <= и >= тоже следует перегружать парами. Ниже приведен полный список операторов, которые можно перегрузить:
Унарные операторы: +, -, !, ~, ++, --, true, false.
Бинарные операторы: +, -, *, /, %, &, |, ^, <<, >>, ==, !=, >, <, >=, <=.
12.4. Вопросы для самопроверки
1. Поддерживает ли язык C# полиморфизм? Подкрепите свою точку
зрения примерами кода на языке C#.
2. Каковы определения внутренней и внешней общности?
3. Являются ли перегрузки операторов нестатическими членами
класса?
12.5. Задания для самопроверки
1. Покажите действие принципа полиморфизма на объектах из за-
дания 1 раздела 9.
2. Опишите биологические процессы объектов задания 1 раздела 9
перегрузками методов.
91
13. КОЛЛЕКЦИИ: ВИДЫ И НАЗНАЧЕНИЕ
13.1. Понятие коллекций
В предыдущих разделах рассматривалось создание структур дан­ных и манипуляции ими. В данном разделе рассматриваются предвари­тельно распределенные по пакетам классы структур данных, предос­тавленные .NET Framework. Эти классы называются коллекциями клас­сов (collection classes): в них сохранены коллекции данных. Каждый эк­земпляр одного из этих классов называется коллекцией, представляю­щей собой набор элементов. С помощью коллекций классов вместо соз­дания структур данных программист просто использует существующие структуры данных, не заботясь об их реализации. Данная методология представляет собой замечательный пример повторного использования кода. Разработчики тратят гораздо меньше времени на написание кодов и ожидают очень высокой производительности за счет доведения до максимума скорости исполнения и сведения к минимуму потребления ресурсов памяти.
Некоторыми примерами коллекций являются карты в карточной игре, любимые песни, сохраненные на компьютере, а также записи о недвижимости в реестре сделок. MS .NET Framework предоставляет го- товые компоненты многократного использования; разработчику нет не­обходимости записывать собственные коллекции классов. Коллекции стандартизированы, поэтому их легко использовать в любых программ­ных приложениях, не вдаваясь в подробности реализации. Коллекции создаются для многократного применения. Они настроены на оператив­ное исполнение, а также на эффективное использование ресурсов памя­ти.
92
13.2. Типы коллекций
Следует тщательно выбирать класс коллекции. Использование неправильного типа может привести к ограничению возможностей использования коллекции. В общем случае не следует использовать типы в пространстве имен System.Collections, если явным образом не нужна платформа .NET Framework версии 1.1. Предпочитаются универсальная и параллельная версии коллекции, так как они обладают большей типобезопасностью и содержат другие улучшения.
Необходимо ответить на следующие вопросы:
• Нужен ли последовательный список, элемент которого обычно
удаляется сразу после извлечения его значения?
– Если да, то рассмотрите возможность использования класса Queue или универсального класса Queue(Of T), если требуется поведение по принципу «первым поступил – первым обслужен» (FIFO). Рассмотрите возможность использования класса Stack или универсального класса Stack(Of T), если требуется поведение по принципу «последним поступил – первым обслужен» (LIFO). Для безопасного доступа из нескольких потоков следует использовать параллельные версии классов ConcurrentQueue(Of T) и ConcurrentStack(Of T).
– Если нет, то следует выбирать из остальных типов коллекций.
• Нужен ли доступ к элементам в определенном порядке (FIFO,
LIFO) или в произвольным порядке?
– Класс Queue, универсальный класс Queue(Of T) или универсальный класс ConcurrentQueue(Of T) предоставляют доступ по принципу FIFO. Дополнительные сведения см. в разделе «Преимущества использования потокобезопасных коллекций».
– Класс Stack, универсальный класс Stack(Of T) или универсальный класс ConcurrentStack(Of T) предоставляют доступ по принципу LIFO. Дополнительные сведения см. в разделе «Преимущества использования потокобезопасных коллекций».
93
– Универсальный класс LinkedList(Of T) предоставляет последовательный доступ от начала к концу списка или наоборот.
• Необходимо ли иметь доступ к каждому элементу по индексу?
– Классы ArrayList и StringCollection, и универсальный класс List(Of T) предоставляют доступ к своим элементам по индексу с отсчетом от нуля.
– Классы Hashtable, SortedList, ListDictionary и StringDictionary, а также универсальные классы Dictionary(Of TKey, TValue) и SortedDictionary(Of TKey, TValue) предоставляют доступ к своим элементам по ключу.
– Классы NameObjectCollectionBase и NameValueCollection, а также универсальные классы KeyedCollection(Of TKey, TItem) и SortedList(Of TKey, TValue) предоставляют доступ к своим элементам по индексу с отсчетом от нуля или по ключу.
• Будет ли каждый элемент содержать только одно значение, сочетание из одного ключа и одного значения или сочетание из одного ключа и нескольких значений?
– Одно значение. Можно использовать любую из коллекций, основанных на интерфейсе IList или на универсальном интерфейсе IList(Of T).
– Один ключ и одно значение. Можно использовать любую из коллекций, основанных на интерфейсе IDictionary или на универсальном интерфейсе IDictionary(Of TKey, TValue).
– Одно значение с внедренным ключом. Можно использовать универсальный класс KeyedCollection(Of TKey, TItem).
– Один ключ и несколько значений. Можно использовать класс NameValueCollection.
• Нужна ли возможность отсортировать элементы в порядке,
отличном от порядка их поступления?
– Класс Hashtable сортирует свои элементы по их хэш-коду.
– Класс SortedList и универсальные классы SortedDictionary(Of TKey, TValue) и SortedList(Of TKey, TValue) сортируют свои элементы по
94
их ключам на основе реализации интерфейса IComparer и универсального интерфейса IComparer(Of T).
– ArrayList предоставляет метод Sort, который принимает реализацию IComparer в качестве параметра. Его универсальный аналог – универсальный класс List(Of T) предоставляет метод Sort, который принимает реализацию универсального интерфейса IComparer(Of T) в качестве параметра.
• Необходимы ли быстрый поиск и извлечение данных?
– ListDictionary быстрее, чем Hashtable для небольших коллекций (10 элементов или меньше). Универсальный класс Dictionary(Of TKey, TValue) предоставляет более быстрый просмотр, чем универсальный класс SortedDictionary(Of TKey, TValue). Многопотоковой реализацией является класс ConcurrentDictionary(Of TKey, TValue). Класс ConcurrentBag(Of T) предоставляет быструю многопотоковую вставку для неупорядоченных данных.
• Нужна ли коллекция только для хранения строк?
– Классы StringCollection (основанный на IList) и StringDictionary (основанный на IDictionary) находятся в пространстве имен System.Collections.Specialized.
– Кроме того, можно использовать любой из универсальных классов коллекций в пространстве имен System.Collections.Generic как строго типизированную строковую коллекцию, указав класс String в качестве аргумента универсального типа.
13.3. Примеры работы с коллекциями
В большинстве языков программирования обычные массивы имеют фиксированный размер: их нельзя изменять динамически для соответ­ствия требованиям времени исполнения и необходимой памяти про­граммному приложению. В некоторых приложениях ограничение по размеру представляет собой довольно серьезную проблему для разра­ботчиков. Им приходится выбирать между применением массивов дос­таточно большого фиксированного размера для сохранения максималь-
95
ного числа элементов, которое может потребоваться программе, и ис­пользованием динамических структур данных, которые могут расши­рять и сокращать объем памяти, необходимый для сохранения данных в ответ на изменяющиеся требования программы во время исполнения.
Коллекция класса ArrayList .NET Framework имитирует функцио- нальность традиционных массивов и обеспечивает динамическое изме­нение размера коллекции посредством методов класса. В любой момент времени коллекция ArrayList содержит определенное число элементов, меньшее или равное емкости – количеству элементов, зарезервирован­ных в текущее время для коллекции ArrayList. Программа может мани­пулировать емкостью посредством свойства Capacity класса ArrayList. При необходимости расширения класса ArrayList текущая емкость (ca- pacity) удваивается по умолчанию. Особенностями работы динамиче­ского массива является то, что результатом вставки в класс ArrayList дополнительных элементов с текущим размером, меньшим, чем ем­кость, становится ускорение выполнения операции, а операция вставки в класс ArrayList элемента, который должен расширяться для соответст­вия новому элементу, выполняется достаточно медленно.
Можно воспользоваться методом TrimToSize класса ArrayList для установки точного размера (подгонки) класса ArrayList. При этом опти­мизируется использование памяти класса ArrayList. Здесь следует со­блюдать осторожность: если программа должна вставить дополнитель­ные элементы, то процесс замедлится, потому что класс ArrayList дол­жен расширяться динамически (подгонка не оставляет места для рас­ширения).
Приращение емкости по умолчанию – удвоение размера класса Ar- rayList – может показаться пустым расходом пространства для сохране­ния, однако удвоение емкости является эффективным способом быстро­го расширения класса ArrayList «практически до нужного размера». При этом использование времени становится более эффективным, не­жели при увеличении размера класса ArrayList по одному элементу во время ответа на операции вставки.
96
Все классы являются производными от класса Object, поэтому класс ArrayList может содержать объекты любого типа. В табл. 13.1 пе­речислены некоторые полезные методы класса ArrayList.
Таблица 13.1
Основные методы класса ArrayList
Метод Описание
Add Добавление объекта в класс ArrayList Clear Удаление всех элементов из класса ArrayList Contains Возвращение значения true(false), если указанный объект ob-
ject находится (отсутствует) в классе ArrayList
IndexOf Возвращение указателя первого появления указанного объек-
та в классе ArrayList Insert Вставка объекта object согласно заданному индексу Remove Удаление первого появления указанного объекта RemoveAt Удаление объекта по заданному индексу RemoveRange Удаление заданного количества элементов, начиная с заданно-
го индекса в классе ArrayList Sort Сортировка класса ArrayList TrimToSize Задание емкости (Capacity) класса ArrayList текущим количе-
ством элементов в классе
Давайте создадим динамический массив и проделаем следующий на­бор операций: поместим туда 5 чисел; одну строку по индексу 3; удалим элемент по индексу 0; удалим элемент 4; перевернем элементы массива в зеркальном порядке.
ArrayList aList = new ArrayList(); for (int i = 0; i < 5; i++) aList.Add(i); aList.Insert(3, "Строка");
aList.RemoveAt(0); aList.Remove(4);
aList.Reverse();
97
//Вывод на экран foreach(object obj in aList) Console.Write(obj + " "); Console.Write(aList.IndexOf("Строка"));
Теперь на экране мы получим 3 “Строка” 2 1 1. Обратите внимание на последнюю единицу – это индекс элемента «Строка», но ведь мы ее добавляли по индексу 3. Все дело в том, что динамический массив сам уплотняется, не оставляя пустых мест внутри себя после удаления.
13.4. Вопросы для самопроверки
1. Когда следует использовать типы в пространстве имен
System.Collections?
2. Какой тип коллекций используется для создания буферов типа
FIFO? Для типа LIFO?
3. Для каких целей следует использовать Dictionary(Of TKey,
TValue)?
4. Какие классы коллекций поддерживают автоматическую сорти-
ровку? В чем принципиальное различие алгоритмов сортировки?
5. В каком классе коллекций следует хранить строки?
6. Как классу ArrayList удается хранить разные типы данных?
13.5. Задания для самопроверки
1. Добавьте в реализацию задания 2 из раздела 5 возможность динамического добавления вопросов перед тестированием. Формирование вопросов и непосредственно тестирование проводится рамках одной сессии.
2. Создайте программу – телефонный справочник, наполнение которого и чтение выполняется в рамках одной сессии. Поиск в книге должен осуществляться как по имени персоны, так и по номеру.
98
3. Модифицируйте программу из предыдущего задания так, чтобы для одной персоны можно было назначить несколько телефонных номеров с описаниями типа «домашний», «рабочий».
4*. Разработайте приложение, использующее стек для обхода дерева в глубину. Тип для узла дерева содержит поле для коллекции ссылок на своих потомков и поле для имени узла. Обход дерева осуществляется в цикле до тех пор, пока стек не пуст. В цикле из стека достаётся узел дере­ва, выдаётся имя узла, потомки узла добавляются в стек.
5*1. Разработайте приложение, использующее очередь для обхода де­рева в ширину. Тип для узла дерева содержит поле для коллекции ссы­лок на своих потомков и поле для номера узла. Обход дерева осуществ­ляется в цикле до тех пор, пока очередь не пуста.
1
Звездочка указывает на задачи с повышенной сложностью.
99
14. GENERICS. LAMBDA. LINQ
14.1. Обобщенные типы
Обобщенные типы (англ. Generics) – особые типы, которые определяют взаимодействия для нескольких типов. Они также известны как шаблонные типы. Основное их предназначение – описывать взаимодействия над однородными типами без дублирования кода. Классическим примером использования обобщенных типов являются арифметические операции над различными типами данных. Например:
public class Summator<T> { public T Sum(T o1, T o2) { return o1 + o2; } }
Такой класс может выполнять операции сложения над типами int, long, double и другими:
Summator<int> si = new Summator<int>(); si.Sum(2, 4);
Summator<float> sf = new Summator<float>(); si.Sum(2.3, 1.2);
Generics получили широкое распространение на практике для оперирования коллекциями:
List<int>, List<Student>
В настоящее время на основе шаблонных типов работают такие сложные механизмы, как транслирование объектов из БД в память, преобразование одних типов к другим через явно описанные правила, регистрация сервисов и компонент для вызова из любой точки
100
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]