Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
САОД_ответы_catsto_NEW.doc
Скачиваний:
17
Добавлен:
16.04.2019
Размер:
365.57 Кб
Скачать
  1. Обобщенные контейнеры .Net. Интерфейс iEnumerable и оператор foreach. Сравнение обобщенных контейнеров и ArrayList.

Обобщённое программирование — парадигма программирования, заключающаяся в таком описании данных и алгоритмов, которое можно применять к различным типам данных, не меняя само это описание. Средства обобщённого программирования реализуются в языках программирования в виде тех или иных синтаксических средств, дающих возможность описывать данные (типы данных) и алгоритмы (процедуры, функции, методы), параметризуемые типами данных.

В языке C++ обобщённое программирование основывается на понятии «шаблон», обозначаемом ключевым словом template. Широко применяется в стандартной библиотеке C++ (STL).

Стандартная библиотека шаблонов (STL) (Standard Template Library) — набор согласованных обобщённых алгоритмов, контейнеров, средств доступа к их содержимому и различных вспомогательных функций.

Обобщённые контейнеры – это контейнеры, при объявлении которых мы можем указать, какой тип данных будет хранится в нём (наподобие шаблонов). В C# это делается так:

System.Collections.Generic.List<string> L; - список со string-ами.

IEnumerable - интерфейс

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

Foreach применяется, если нужно «пробежаться» по всему контейнеру.

Итераторы в .NET Framework называются 'перечислителями' (enumerators) и представлены интерфейсом IEnumerator (для использования оператора foreach в своём контейнере). IEnumerator реализует метод MoveNext(), который переходит к следующему элементу и указывает достигнут ли конец коллекции; свойство Current служит для получения значения указываемого элемента; дополнительный метод Reset() возвращает перечислитель на его исходную позицию. Перечислитель первоначально указывает на специальное значение перед первым элементом, поэтому вызов MoveNext() необходим для начала итерации.

Перечислители обычно передаются вызовом метода GetEnumerator() объекта, реализующего интерфейс IEnumerable. Классы контейнеров обычно реализуют этот интерфейс. Тем не менее, выражение foreach в языке C# может оперировать любым объектом, поддерживающим подобный метод, даже если он не реализует IEnumerable. Оба интерфейса были расширены в обобщенных версиях .NET 2.0.

Следующий пример показывает простое использование итераторов в C# 2.0:

// 'явная' версия

IEnumerator<MyType> iter = list.GetEnumerator();

while (iter.MoveNext())

Console.WriteLine(iter.Current);

// 'неявная' версия

foreach (MyType value in list)

Console.WriteLine(value);

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

Совместные циклы имеются в некоторых языках программирования (C#, Java, JavaScript, Perl, Python, PHP, LISP, Tcl и др.) — они позволяют выполнять цикл по всем элементам заданной коллекции объектов. В определении такого цикла требуется указать только коллекцию объектов и переменную, которой в теле цикла будет присвоено значение обрабатываемого в данный момент объекта (или ссылка на него). В различных языках программирования синтаксис оператора различен:

C#:

foreach (type item in set)

{ //использование item}

ArrayList - класс

Реализует интерфейс IList с помощью массива с динамическим увеличением размера до нужного значения.

Проблемы возникают в связи с тем, что мы не всегда знаем, что пихаем в ArrayList

Класс ArrayList реализует динамический массив, размеры которого автоматически увеличиваются и уменьшаются по мере надобности. Динамические массивы работают чуть медленнее обычных массивов, но они заметно упрощают многие задачи программирования. Кроме того, в отличие от большинства массивов класс ArrayList является гетерогенным, то есть позволяет хранить объекты разных типов.

Существует много коллекций в Collections. Это ArrayList, BitArray, Hashtable, Stack, Queue и пр. Их недостатки в том, что они не типизированные. Иногда этого достаточно, если работа идет с одним типом объектов. Но во многих ситуациях предпочтительнее иметь дело с типизированными контейнерами, такими, которые аналогичны контейнерам STL.

Эта возможность предоставляется средствами библиотеки Collections.Generic. Это Dictionary<TKey, TValue>, List<TValue>, HashSet<TValue>, LinkedList<TValue> и др.

Все эти коллекции реализуют интерфейс IEnumerable (перечислимый) и могут обрабатываться оператором foreach.

Например,

string[] words ={ "the", "fox", "jumped", "over", "the", "dog" };

LinkedList<string> sentence = new LinkedList<string>(words);

foreach (string s in sentence)

{

Console.WriteLine(s);

}

  1. Реализация объектов с подсчетом ссылок. Эффективность создания копий в C++. Другие применения объектов с подсчетом ссылок.

Объекты с подсчетом ссылок:

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

Одним из методов, позволяющих эффективно выполнять копирование – использование подсчета ссылок. Рассмотрим один из способов реализации такого механизма на примере CStr.

Идея состоит в том, что объект строится в 2 этапа – объект для приложений и объект для “управления ресурсом”. В нашем примере CStr и _str. _str ведет подсчет ссылок на себя, CStr отвечает за правильное “информирование” _str о его использовании.

Теперь при создании копии CStr, достаточно сослаться на тот же экземпляр _str и увеличить у него количество ссылок, а при уничтожении CStr не разрушать _str, а уменьшить количество ссылок. Задача же объектов класса _str правильно подсчитывать количество пользователей и освободить ресурс, когда пользователей больше нет.

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

class CStr;

class _str {

char* m_pszData;