- •Оглавление
- •Лабораторная работа №8 Синтаксис интерфейса
- •Реализация интерфейса
- •Работа с объектами через интерфейсы. Операции is и as
- •Интерфейсы и наследование
- •Стандартные интерфейсы .Net
- •Сравнение объектов
- •Сортировка по разным критериям (интерфейс iComparer)
- •Перебор объектов (интерфейс iEnumerable) и итераторы
- •Пространство имен System.Collections
- •Класс ArrayList
- •Индивидуальные задания
- •Вариант 0
- •Вариант 1
- •Вариант 2
- •Вариант 3
- •Вариант 4
- •Вариант 5-20
- •Пример выполнения варианта №0
Пространство имен System.Collections
В пространстве имен System.Collections определены наборы стандартных коллекций и интерфейсов, которые реализованы в этих коллекциях. В таблице 8.1 приведены наиболее важные интерфейсы, часть из которых мы уже изучали в разделе «Стандартные интерфейсы .NET.
Таблица 8.1. Интерфейсы пространства имен System.Collections
Интерфейс |
Назначение |
ICollection |
Определяет общие характеристики (например, размер) для набора элементов |
IComparer |
Позволяет сравнивать два объекта |
IDictionary |
Позволяет представлять содержимое объекта в виде пар «имя-значение» |
IDictionaryEnumerator |
Используется для нумерации содержимого объекта, поддерживающего интерфейс IDictionary |
IEnumerable |
Возвращает интерфейс IEnumerator для указанного объекта |
IEnumerator |
Обычно используется для поддержки оператора foreach в отношении объектов |
IHashCodeProvider |
Возвращает хеш-код для реализации типа с применением выбранного пользователем алгоритма хеширования |
IList |
Поддерживает методы добавления, удаления и индексирования элементов в списке объектов |
В таблице 8.2 перечислены основные коллекции, определенные в пространстве System.Collections.
Таблица 8.2. Коллекции пространства имен System.Collections
Класс |
Назначение |
Важнейшие из реализованных интерфейсов |
ArrayList |
Массив, динамически изменяющий свой размер |
IList, ICollection, IEnumerable, ICloneable |
BitArray |
Компактный массив для хранения битовых значений |
ICollection, IEnumerable, ICloneable |
Hashtable |
Хеш-таблица |
IDictionary, ICollection, IEnumerable, ICloneable |
Queue |
Очередь |
ICollection, ICloneable, IEnumerable |
SortedList |
Коллекция, отсортированная по ключам. Доступ к элементам — по ключу или по индексу |
IDictionary, ICollection, IEnumerable, ICloneable |
Stack |
Стек |
ICollection, IEnumerable |
Пространство имен System.Collections.Specialized включает специализированные коллекции, например, коллекцию строк StringCollection и хеш-таблицу со строковыми ключами StringDictionary.
В качестве примера стандартной коллекции рассмотрим класс ArrayList.
Класс ArrayList
Основным недостатком обычных массивов является то, что объем памяти, необходимый для хранения их элементов, должен быть выделен до начала работы с массивом. Класс ArrayList позволяет программисту не заботиться о выделении памяти и хранить в одном и том же массиве элементы различных типов.
По умолчанию при создании объекта типа ArrayList строится массив из 16 элементов типа object. Можно задать желаемое количество элементов в массиве, передав его в конструктор или установив в качестве значения свойства Capacity, например:
ArrayList arr1 = new ArrayList(); // создается массив из 16 элементов
ArrayList arr2 = new ArrayList(1000); // создается массив из 1000 элементов
ArrayList arr3 = new ArrayList();
arr3.Capacity = 1000; // количество элементов задается
Основные методы и свойства класса ArrayList перечислены в таблице 8.3.
Таблица 8.3. Основные элементы класса ArrayList
Элемент |
Вид |
Описание |
Capacity |
Свойство |
Емкость массива (количество элементов, которые могут храниться в массиве) |
Count |
Свойство |
Фактическое количество элементов массива |
Item |
Свойство |
Получить или установить значение элемента по заданному индексу |
Add |
Метод |
Добавление элемента в конец массива |
AddRange |
Метод |
Добавление серии элементов в конец массива |
BinarySearch |
Метод |
Двоичный поиск в отсортированном массиве или его части |
Clear |
Метод |
Удаление всех элементов из массива |
Clone |
Метод |
Поверхностное копирование элементов одного массива в другой массив |
CopyTo |
Метод |
Копирование всех или части элементов массива в одномерный массив |
GetRange |
Метод |
Получение значений подмножества элементов массива в виде объекта типа ArrayList |
IndexOf |
Метод |
Поиск первого вхождения элемента в массив (возвращает индекс найденного элемента или –1, если элемент не найден) |
Insert |
Метод |
Вставка элемента в заданную позицию (по заданному индексу) |
InsertRange |
Метод |
Вставка группы элементов, начиная с заданной позиции |
LastIndexOf |
Метод |
Поиск последнего вхождения элемента в одномерный массив |
Remove |
Метод |
Удаление первого вхождения заданного элемента в массив |
RemoveAt |
Метод |
Удаление элемента из массива по заданному индексу |
RemoveRange |
Метод |
Удаление группы элементов из массива |
Reverse |
Метод |
Изменение порядка следования элементов на обратный |
SetRange |
Метод |
Установка значений элементов массива в заданном диапазоне |
Sort |
Метод |
Упорядочивание элементов массива или его части |
TrimToSize |
Метод |
Установка емкости массива, равной фактическому количеству элементов |
Класс ArrayList реализован через класс Array, то есть содержит закрытое поле этого класса. Поскольку все типы в C# являются потомками класса object, массив может содержать элементы произвольного типа. Даже если в массиве хранятся обычные целые числа, то есть элементы значимого типа, внутренний класс является массивом ссылок на экземпляры типа object, которые представляют собой упакованный тип-значение. Соответственно, при занесении в массив выполняется упаковка, а при извлечении – распаковка элемента. Это не может не сказаться на быстродействии алгоритмов, использующих ArrayList.
Если при добавлении элемента в массив оказывается, что фактическое количество элементов массива превышает его емкость, она автоматически удваивается, то есть происходит повторное выделение памяти и переписывание туда всех существующих элементов.
Пример занесения элементов в экземпляр класса ArrayList:
arr1.Add( 123 );
arr1.Add( -2 );
arr1.Add( "Вася" );
Доступ к элементу выполняется по индексу, однако при этом необходимо явным образом привести полученную ссылку к целевому типу, например:
int a = (int) arr1[0];
int b = (int) arr1[1];
string s = (string) arr1[2];
Попытка приведения к типу, не соответствующему хранимому в элементе, вызывает генерацию исключения InvalidCastException.
Для повышения надежности программ применяется следующий прием: экземпляр класса ArrayList объявляется закрытым полем класса, в котором необходимо хранить коллекцию значений определенного типа, а затем описываются методы работы с этой коллекцией, делегирующие свои функции методам ArrayList. Этот способ иллюстрируется в листинге 8.8, где создается класс для хранения объектов типа Monster и производных от него. По сравнению с аналогичным листингом из раздела «Виртуальные методы», в котором используется обычный массив, у нас появилась возможность хранить в классе Stado произвольное количество элементов.
Листинг 8.8. – Коллекция объектов
using System;
using System.Collections;
namespace ConsoleApplication1
{
class Monster { ... }
class Daemon : Monster { ... }
class Stado : IEnumerable
{
private ArrayList list;
public Stado() { list = new ArrayList(); }
public void Add( Monster m ) { list.Add( m ) ; }
public void RemoveAt( int i ) { list.RemoveAt( i ); }
public void Clear() { list.Clear(); }
public IEnumerator GetEnumerator()
{ return list.GetEnumerator(); }
}
class Class1
{ static void Main()
{
Stado stado = new Stado();
stado.Add( new Monster( "Monia" ) );
stado.Add( new Monster( "Monk" ) );
stado.Add( new Daemon ( "Dimon", 3 ) );
stado.RemoveAt( 1 );
foreach ( Monster x in stado ) x.Passport();
}
}
}
Результат работы программы:
Monster Monia health = 100 ammo = 100
Daemon Dimon health = 100 ammo = 100 brain = 3
Недостатком этого решения является то, что для каждого метода стандартной коллекции приходится описывать метод-оболочку, вызывающий стандартный метод. Хотя это и несложно, но несколько неизящно. В C#, начиная с версии 2.0, появились классы-прототипы (generics), позволяющие решить эту проблему. Мы рассмотрим их в следующем разделе.