Реализация интерфейса IComparer

Интерфейсы, используемые коллекциями. Применение перечислителя типа IDictionaryEnumerator. Специальные и наблюдаемые коллекции. Итераторы и оператор yield. Основные обобщенные коллекции. Реализация интерфейсов IComparer, IEnumerable и IEnumerator.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 17.05.2015
Размер файла 1,2 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

NameValueCollection

Предназначен для отсортированных коллекций, в которых хранятся пары "ключ-значение", причем и ключ, и значение относятся к типу string

OrderedDictionary

Предназначен для коллекций, в которых хранятся индексируемые пары "ключ-значение"

StringCollection

Предназначен для коллекций, оптимизированных для хранения символьных строк

StringDictionary

Предназначен для хеш-таблиц, в которых хранятся пары "ключ-значение", причем и ключ, и значение относятся к типу string

Кроме того, в пространстве имен System.Collections определены три базовых абстрактных класса: CollectionBase, ReadOnlyCollectionBase и DictionaryBase. Эти классы могут наследоваться и служить в качестве отправной точки для разработки собственных специальных коллекций. [2]

5.2 Наблюдаемые коллекции

В случае если нужна информация о том, когда элементы коллекции удаляются или добавляются, можно использовать класс ObservableCollection<T>. Этот класс был определен для WPF и предназначен для того, чтобы пользовательский интерфейс мог получать информацию об изменениях коллекции. По этой причине он включен в сборку WindowsBase, следовательно, на нее необходимо сослаться. Пространство имен этого класса -- System.Collections.ObjectModel. [2]

Класс ObservableCollection<T> унаследован от базового класса Collection<T>, который может применяться для создания специальных коллекций; он использует внутри себя List<T>. Методы базового класса SetItem() и RemoveItem() переопределены для инициации события CollectionChanged. Клиенты этого класса могут регистрироваться на это событие, используя интерфейс INotifyCollectionChanged.

В следующем примере показано применение ObservableCollection<string>, при этом метод Data_CollectionChanged регистрируется на событие CollectionChanged.

Два элемента добавляются в конец коллекции, затем еще один вставляется и один удаляется:

var data = new ObservableCollection<string>();

data.CollectionChanged += Data_CollectionChanged;

data.Add("One");

data.Add("Two");

data.Insert(1, "Three");

data.Remove("One");

Метод Data_CollectionChanged принимает аргумент NotifyCollection Changed EventArgs, содержащий информацию об изменениях коллекции.

Свойство Action предоставляет информацию о том, был элемент добавлен или удален. Для удаленных элементов устанавливается свойство OldItems, перечисляющее удаленные элементы.

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

6. Битовые коллекции

Если требуется иметь дело с множеством битов, можно применить класс BitArray и структуру BitVector32. Класс BitArray расположен в пространстве имен System.Collections, a BitVector32 -- в пространстве System.Collections.Specialized. Наиболее важное отличие между этими двумя типами состоит в том, что BitArray имеет изменяемый размер, а это удобно, когда необходимое количество бит известно заранее, и оно велико. Структура BitVector32 основана на стеке, и потому работает быстрее. BitVector32 содержит только 32 бита, которые хранятся в целом числе. [3]

6.1 Класс BitArray

Класс BitArray служит для хранения отдельных битов в коллекции. А поскольку в коллекции этого класса хранятся биты, а не объекты, то своими возможностями он отличается от классов других коллекций. Тем не менее, в классе BitArray реализуются интерфейсы ICollection и IEnumerable как основополагающие элементы поддержки всех типов коллекций. Кроме того, в классе BitArray реализуется интерфейс ICloneable. [2]

В классе BitArray определено несколько конструкторов. Так, с помощью приведенного ниже конструктора можно сконструировать объект типа BitArray из массива логических значений:

public BitArray(bool[] values)

В данном случае каждый элемент массива values становится отдельным битом в коллекции. Это означает, что каждому элементу массива values соответствует отдельный бит в коллекции. Более того, порядок расположения элементов в массиве values сохраняется и в коллекции соответствующих им битов. Коллекцию типа BitArray можно также составить из массива байтов, используя следующий конструктор: [2]

public BitArray(byte[] bytes)

Здесь битами в коллекции становится уже целый их набор из массива bytes, причем элемент bytes [0] обозначает первые 8 битов, элемент bytes [1] вторые 8 битов и т.д. [2]

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

В классе BitArray определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Методы этого класса приведены ниже. [3]

В классе BitArray не поддерживается метод Synchronized(). Это означает, что для коллекций данного класса синхронизированная оболочка недоступна, а свойство IsSynchronized всегда имеет логическое значение false. Тем не менее, для управления доступом к коллекции типа BitArray ее можно синхронизировать для объекта, предоставляемого в упоминавшемся ранее свойством SyncRoot. [2]

And()

Выполняет операцию логического умножения (И) битов вызывающего объекта и коллекции value. Возвращает коллекцию типа BitArray, содержащую результат

Get()

Возвращает значение бита, указываемого по индексу

Not()

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

Or()

Выполняет операцию логического сложения (ИЛИ) битов вызывающего объекта и коллекции value. Возвращает коллекцию типа BitArray, содержащую результат. [2]

Set()

Устанавливает бит, указываемый по индексу index, равным значению value

SetAll()

Устанавливает все биты равными значению value

Xor()

Выполняет логическую операцию исключающее (ИЛИ) над битами вызывающего объекта и коллекции value. Возвращает коллекцию типа BitArray, содержащую результат. [2]

В классе BitArray определяется также собственное свойство, помимо тех, что указаны в интерфейсах, которые в нем реализуются:

public int Length { get; set; }

Свойство Length позволяет установить или получить количество битов в коллекции. Следовательно, оно возвращает такое же значение, как и стандартное свойство Count, определяемое для всех коллекций. В отличие от свойства Count, свойство Length доступно не только для чтения, но и для записи, а значит, с его помощью можно изменить размер коллекции типа BitArray. [3]

6.2 Структура BitVector

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

Если нужно больше, можно применять множество значений BitVector32 или же BitArray. Класс BitArray при необходимости может расти, а структура BitVector32 лишена такой возможности. [2]

Ниже перечислены члены структуры BitVector32, которые существенно отличаются от BitArray:

Data

Свойство Data возвращает данные BitVector32 в виде целого числа.

Item

Значение BitVector32 может быть установлено с использованием целого числа. Индексатор перегружен: получать и устанавливать значения можно с использованием маски или секции типа BitVector32.Section.

CreateMask()

Статический метод, который позволяет создавать маску для доступа к определенным битам Bitvector32.

CreateSelection()

Статический метод, который позволяет создавать несколько секций внутри 32 бит. В приведенном ниже примере создается структура BitVector32 с помощью конструктора по умолчанию, при этом все 32 бита инициализируются false. Затем создаются маски для доступа к битам внутри битового вектора. Первый вызов CreateMask() создает маску для доступа к первому биту. После вызова CreateMask() значение bitl равно 1. [2]

Еще один вызов CreateMask() возвращает маску для доступа ко второму биту, которая равна 2.bit3 имеет значение 4 для доступа к биту номер 3. bit4 имеет значение 8 для доступа к биту номер 4.Затем маски используются с индексатором для доступа к битам внутри вектора бит и соответствующей установки полей:

var bitsl = new BitVector32 () ;

int bitl = BitVector32.CreateMask();

int bit2 = BitVector32.CreateMask(bitl);

int bit3 = BitVector32.CreateMask(bit2);

int bit4 = BitVector32.CreateMask(bit3);

int bit5 = BitVector32.CreateMask(bit4);

bitsl[bitl] = true;

bitsl[bit2] = false;

bitsl[bit3] = true;

bitsl[bit4] = true;

bitsl[bi15] = true;

Console.WriteLine(bits1);

7. Реализация интерфейса IComparable

Если требуется отсортировать коллекцию, состоящую из объектов определяемого пользователем класса, при условии, что они не сохраняются в коллекции класса SortedList, где элементы располагаются в отсортированном порядке, то в такой коллекции должен быть известен способ сортировки содержащихся в ней объектов. С этой целью можно, в частности, реализовать интерфейс IComparable для объектов сохраняемого типа. Интерфейс IComparable доступен в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия. [2]

Если требуется отсортировать объекты, хранящиеся в необобщенной коллекции, то для этой цели придется реализовать необобщенный вариант интерфейса IComparable. В этом варианте данного интерфейса определяется только один метод, CompareTo(), который определяет порядок выполнения самого сравнения. Ниже приведена общая форма объявления метода CompareTo():

int CompareTo(object obj)

В методе CompareTo() вызывающий объект сравнивается с объектом obj. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное -- если значение вызывающего объекта больше, чем у объекта obj; и отрицательное -- если значение вызывающего объекта меньше, чем у объекта obj. А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта obj не подходит для сравнения с вызывающим объектом, то в методе CompareTo() может быть сгенерировано исключение ArgumentException. [2]

Если требуется отсортировать объекты, хранящиеся в обобщенной коллекции, то для этой цели придется реализовать обобщенный вариант интерфейса IComparable<T>. В этом варианте интерфейса IComparable определяется приведенная ниже обобщенная форма метода CompareTo():

int CompareTo(Т other). [2]

В методе CompareTo() вызывающий объект сравнивается с другим объектом other.

Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное -- если значение вызывающего объекта больше, чем у объекта другого other; и отрицательное если значение вызывающего объекта меньше, чем у другого объекта other. А для сортировки по убывающей можно обратить результат сравнения объектов. При реализации обобщенного интерфейса IComparable<T> имя типа реализующего класса обычно передается в качестве аргумента типа. [2]

8. Реализация интерфейса IComparer

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

Интерфейс IComparer существует в двух формах: обобщенной и необобщенной. Несмотря на сходство применения обеих форм данного интерфейса, между ними имеются некоторые, хотя и небольшие, отличия.

В необобщенном интерфейсе IComparer определяется только один метод Compare():

int Compare(object x, object у)

В методе Compare() сравниваются объекты х и у. Для сортировки объектов по нарастающей конкретная реализация данного метода должна возвращать нулевое значение, если значения сравниваемых объектов равны; положительное -- если значение объекта х больше, чем у объекта у; и отрицательное -- если значение объекта х меньше, чем у объекта у. А для сортировки по убывающей можно обратить результат сравнения объектов. Если же тип объекта х не подходит для сравнения с объектом у, то в методе CompareTo() может быть сгенерировано исключение ArgumentException. [2]

Объект типа IComparer может быть указан при конструировании объекта класса SortedList, при вызове метода ArrayList.Sort(IComparer), а также в ряде других мест в классах коллекций. Главное преимущество применения интерфейса IComparer заключается в том, что сортировке подлежат объекты тех классов, в которых интерфейс IComparable не реализуется. [2]

Интерфейс IComparer<T> является обобщенным вариантом интерфейса IComparer. В нем определяется приведенный ниже обобщенный вариант метода Compare():

int Compare(Т х, T у)

В этом методе сравниваются объекты х и у и возвращается нулевое значение, если значения сравниваемых объектов равны; положительное -- если значение объекта х больше, чем у объекта у; и отрицательное -- если значение объекта х меньше, чем у объекта у. [2]

9. Перечислители

К элементам коллекции нередко приходится обращаться циклически, например, для отображения каждого элемента коллекции. С этой целью можно, с одной стороны, организовать цикл foreach, а с другой -- воспользоваться перечислителем. Перечислитель -- это объект, который реализует необобщенный интерфейс IEnumerator или обобщенный интерфейс IEnumerator<T>. [2]

В интерфейсе IEnumerator определяется одно свойство, Current, необобщенная форма которого приведена ниже:

object Current {get;}

А в интерфейсе IEnumerator<T> объявляется следующая обобщенная форма свойства Current:

Т Current {get;}

В обеих формах свойства Current получается текущий перечисляемый элемент коллекции. Но поскольку свойство Current доступно только для чтения, то перечислитель может служить только для извлечения, но не видоизменения объектов в коллекции. [2]

В интерфейсе IEnumerator определяются два метода. Первым из них является метод MoveNext(), объявляемый следующим образом:

bool MoveNext()

При каждом вызове метода MoveNext() текущее положение перечислителя смещается к следующему элементу коллекции. Этот метод возвращает логическое значение true, если следующий элемент коллекции доступен, и логическое значение false, если достигнут конец коллекции. Перед первым вызовом метода MoveNext() значение свойства Current оказывается неопределенным. [2]

Для установки перечислителя в исходное положение, соответствующее началу коллекции, вызывается приведенный ниже метод Reset():

void Reset()

После вызова метода Reset() перечисление вновь начинается с самого начала коллекции. Поэтому, прежде чем получить первый элемент коллекции, следует вызвать метод MoveNext(). [2]

В интерфейсе IEnumerator<T> методы MoveNext() и Reset() действуют по тому же самому принципу. Необходимо также обратить внимание на два следующих момента. Во-первых, перечислитель нельзя использовать для изменения содержимого перечисляемой с его помощью коллекции. Следовательно, перечислители действуют по отношению к коллекции как к доступной только для чтения. И во-вторых, любое изменение в перечисляемой коллекции делает перечислитель недействительным.

9.1 Применение обычного перечислителя

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

1) Получить перечислитель, устанавливаемый в начало коллекции, вызвав для этой коллекции метод GetEnumerator(). [2]

2) Организовать цикл, в котором вызывается метод MoveNext(). Повторять цикл до тех пор, пока метод MoveNext() возвращает логическое значение true.

3) Получить в цикле каждый элемент коллекции с помощью свойства Current. [2]

Пример использования перечислителей, заимствованный из источника [2] показан в листинге 8 (см. Приложение А).

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

9.2 Применение перечислителя типа IDictionaryEnumerator

Если для организации коллекции в виде словаря, например типа Hashtable, реализуется необобщенный интерфейс IDictionary, то для циклического обращения к элементам такой коллекции следует использовать перечислитель типа IDictionaryEnumerator вместо перечислителя типа IEnumerator. Интерфейс IDictionaryEnumerator наследует от интерфейса IEnumerator и имеет три дополнительных свойства. Первым из них является приведенное ниже свойство. [3]

DictionaryEntry Entry {get;}

Свойство Entry позволяет получить пару "ключ-значение" из перечислителя в форме структуры DictionaryEntry. Напомним, что в структуре DictionaryEntry определяются два свойства, Key и Value, с помощью которых можно получать доступ к ключу или значению, связанному с элементом коллекции. Ниже приведены два других свойства, определяемых в интерфейсе IDictionaryEnumerator

object Key { get; }

object Value { get; }

С помощью этих свойств осуществляется непосредственный доступ к ключу или значению. [2]

Перечислитель типа IDictionaryEnumerator используется аналогично обычному перечислителю, за исключением того, что текущее значение в данном случае получается с помощью свойств Entry, Key или Value, а не свойства Current. Следовательно, приобретя перечислитель типа IDictionaryEnumerator, необходимо вызвать метод MoveNext(), чтобы получить первый элемент коллекции. А для получения остальных ее элементов следует продолжить вызовы метода MoveNext(). Этот метод возвращает логическое значение false, когда в коллекции больше нет ни одного элемента. [2]

9.3 Реализация интерфейсов IEnumerable и IEnumerator

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

Ниже представлен пример реализации интерфейса IEnumerator

public bool MoveNext()

{

if (index == ints.Length - 1)

{

Reset();

return false;

}

index++;

return true;

}

И пример реализации интерфейса Ienumerable

public IEnumerator GetEnumerator()

{

return this;

}

Иными словами, для того чтобы обратиться к объекту определяемого пользователем класса в цикле foreach, необходимо реализовать интерфейсы IEnumerator и IEnumerable в их обобщенной или необобщенной форме.

10. Итераторы и оператор yield

Итератор представляет собой метод, в котором используется ключевое слово yield для перебора по коллекции или массиву. [3]

Наиболее простой способ создания итератора заключается в реализации метода GetEnumerator для интерфейса IEnumerable, например:

public System.Collections.IEnumerator GetEnumerator()

{

for (int i = 0; i < 10; i++)

{

yield return i;

}

}

Наличие метода GetEnumerator создает тип перечисляемого типа и позволяет использовать оператор foreach statement. Если бы приведенный выше метод был частью определения класса для ListClass, то можно было бы использовать foreach для класса следующим образом [5]

static void Main()

{

ListClass listClass1 = new ListClass();

foreach (int i in listClass1)

{

System.Console.WriteLine(i);

}

}

Оператор foreach вызывает ListClass.GetEnumerator() и использует возвращенный перечислитель для итерации значений. [5]

Кроме того, можно использовать именованные итераторы в поддержку различных возможностей перебора одной и той же коллекции данных. [5]

Например, можно было бы предоставить один итератор, возвращающий элементы по возрастанию, а другой итератора, возвращающий элементы по убыванию. Итератор может также иметь параметры, позволяющие клиентам управлять всем поведением итератора или его часть. Следующий итератор реализует интерфейс IEnumerable при помощи именованного итератора SampleIterator [5]

public System.Collections.IEnumerable SampleIterator(int start, int end)

{

for (int i = start; i <= end; i++)

{

yield return i;

}

}

Именованный итератор вызывается следующим образом. [5]

ListClass test = new ListClass();

foreach (int n in test.SampleIterator(1, 10))

{

System.Console.WriteLine(n);

}

В одном итераторе можно использовать несколько операторов yield, как в следующем примере. [5]

public System.Collections.IEnumerator GetEnumerator()

{

yield return "With an iterator, ";

yield return "more than one ";

yield return "value can be returned";

yield return ".";

}

Результаты можно вывести с помощью оператора foreach. [5]

foreach (string element in new TestClass())

{

System.Console.Write(element);

}

В каждой последовательной итерации цикла foreach (или прямом вызове IEnumerator.MoveNext) следующий текст кода итератора возобновляется после оператора yield и продолжается до конца текста итератора или до оператора yield break.

Итераторы не поддерживают метод IEnumeratorReset(). Для повторной итерации сначала необходимо получить новый итератор. [5]

IEnumerator IEnumerable.GetEnumerator()

{

for (int i = 0; i < books.Length; i++)

{

yield return books[i];

}

}

Метод GetEnumerator() теперь будет являться итератором. Когда будет осуществляться перебор в объекте Library в цикле foreach, то будет идти обращение к вызову yield return books[i]. При обращении к оператору yield return будет сохраняться текущее местоположение. И когда метод foreach перейдет к следующей итерации для получения нового объекта, итератор начнет выполнения с этого местоположения. [3]

В основной программе в цикле foreach выполняется перебор, благодаря реализации итератора:

foreach (Book b in library)

{

Console.WriteLine(b.Name);

}

При реализации итератора в методе GetEnumerator() применять перебор массива в цикле for необязательно. Можно определить несколько вызовов оператора yield return, как показано в примере ниже. [3]

IEnumerator IEnumerable.GetEnumerator()

{

yield return books[0];

yield return books[1];

yield return books[2];

}

В этом случае при каждом вызове оператора yield return итератор также будет запоминать текущее местоположение и при последующих вызовах начинать с него. [3]

10.1 Именованный итератор

Выше для создания итератора был использован метод GetEnumerator. Но оператор yield можно использовать внутри любого метода, только такой метод должен возвращать объект интерфейса IEnumerable. Подобные методы еще называют именованными итераторами. [3]

В листинге 10 (см. Приложение А) приведен пример из источника [3], в котором создается именованный итератор в классе Library.

Определенный здесь итератор - метод IEnumerable GetBooks(int max) в качестве параметра принимает количество выводимых объектов.

public IEnumerable GetBooks(int max)

{

for (int i = 0; i < max; i++)

{

if (i == books.Length)

{

yield break;

}

else

{

yield return books[i];

}

}

}

В процессе работы программы может сложиться, что его значение будет больше, чем длина массива books. И чтобы не произошло ошибки, используется оператор yield break. Этот оператор прерывает выполнение итератора. [3]

Применение итератора:

Library library = new Library();

foreach (Book b in library.GetBooks(5))

{

Console.WriteLine(b.Name);

}

Вызов library.GetBooks(5) будет возвращать набор из не более чем 5 объектов Book. Но так как в примере всего три таких объекта, то в методе GetBooks после трех операций сработает оператор yield break. [3]

if (i == books.Length)

{

yield break;

}

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

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

using System;

using System.Collections;

class MyClass

{

char ch = 'A';

// Этот итератор возвращает буквы английского алфавита,

}

}

Заключение

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

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

Список использованных источников

1. Чистяков, В. Коллекции в .NET Framework Class Library / В. Чистяков // RSDN Magazine. - 2003. № 6. - С. 31-34.

2. Нейгел, Кристиан C# 5.0 и платформа .Net 4.5 для профессионалов / Кристиан Нейгел [и др.].; пер. с англ. Ю.Н. Артеменко - М.: ООО "И.Д. Вильямс", 2014. - 1440 с.

3. Троелсен, Эндрю Язык программирования C# 5.0 и платформа .NET 4.5 / Эндрю Троелсен; пер. с англ. Ю. Н. Артеменко. - 6-е изд. - М.: ООО "И.Д. Вильямс", 2013. - 1311 с.

Приложение

Листинги и результаты работы программ

В листинге 1 представлен пример использования коллекций, работы с элементами, добавление и удаление некоторых элементов.

Листинг 1 - Создание и применение двух коллекций

using System;

using System.Collections;

using System.Collections.Generic;

namespace Collections

{

class Program

{

static void Main(string[] args)

{

// необобщенная коллекция ArrayList

ArrayList objectList = new ArrayList() { 1, 2, "string", 'c', 2.0f };

object obj = 45.8;

objectList.Add(obj);

objectList.Add("string2");

objectList.RemoveAt(0); // удаление первого элемента

foreach (object o in objectList)

{

Console.WriteLine(o);

}

Console.WriteLine("Общее число элементов коллекции: " + objectList.Count);

// обобщенная коллекция List

List<string> countries = new List<string>() { "Россия", "США", "Великобритания", "Китай" };

countries.Add("Франция");

countries.RemoveAt(1); // удаление второго элемента

foreach (string s in countries)

{

Console.WriteLine(s);

}

Console.ReadLine();

}

}

}

Результат работы программы представлен на рисунке А1.

Рисунок А.1 - Создание и применение коллекций ArrayList и List

Листинг 2 - Реализация списка List<T>

using System;

using System.Collections.Generic;

namespace Collections

{

class Program

{

static void Main(string[] args)

{

List<int> numbers = new List<int>() { 1, 2, 3, 45 };

numbers.Add(6); // добавление элемента

numbers.AddRange(new int[] { 7, 8, 9 });

numbers.Insert(0, 666); // вставляем на первое место в списке число 666

numbers.RemoveAt(1); // удаляем второй элемент

foreach (int i in numbers)

{

Console.WriteLine(i);

}

List<Person> persons = new List<Person>(3);

persons.Add(new Person() { Name = "Том" });

persons.Add(new Person() { Name = "Билл" });

foreach (Person p in persons)

{

Console.WriteLine(p.Name);

}

Console.ReadLine();

}

}

class Person

{

public string Name { get; set; }

}

}

Листинг 3 - Использование очереди Queue<Т>

using System;

using System.Collections.Generic;

namespace Collections

{

class Program

{

static void Main(string[] args)

{

Queue<int> numbers = new Queue<int>();

numbers.Enqueue(3); // очередь 3

numbers.Enqueue(5); // очередь 3, 5

numbers.Enqueue(8); // очередь 3, 5, 8

// получаем первый элемент очереди

int queueElement = numbers.Dequeue(); //теперь очередь 5, 8

Console.WriteLine(queueElement);

Queue<Person> persons = new Queue<Person>();

persons.Enqueue(new Person() { Name = "Tom" });

persons.Enqueue(new Person() { Name = "Bill" });

persons.Enqueue(new Person() { Name = "John" });

// получаем первый элемент без его извлечения

Person pp = persons.Peek();

Console.WriteLine(pp.Name);

Console.WriteLine("Сейчас в очереди {0} человек", persons.Count);

// теперь в очереди Tom, Bill, John

foreach (Person p in persons)

{

Console.WriteLine(p.Name);

}

// Извлекаем первый элемент в очереди - Tom

Person person = persons.Dequeue(); // теперь в очереди Bill, John

Console.WriteLine(person.Name);

Console.ReadLine();

}

}

class Person

{

public string Name { get; set; }

}

}

Результат работы программы можно увидеть на рисунке А.2.

Рисунок А.2 - Результат использование очереди Queue<Т>

Листинг 4 - Пример использования списка LinkedList<T>

using System;

using System.Collections.Generic;

namespace Collections

{

class Program

{

static void Main(string[] args)

{

LinkedList<int> numbers = new LinkedList<int>();

numbers.AddLast(1); // вставляем узел со значением 1 на последнее место

// так как в списке нет узлов, то последнее будет также и первым

numbers.AddFirst(2); // вставляем узел со значением 2 на первое место

numbers.AddAfter(numbers.Last, 3); // вставляем после последнего узла новый узел со значением 3

// теперь у нас список имеет следующую последовательность: 2, 1, 3

foreach (int i in numbers)

{

Console.WriteLine(i);

}

LinkedList<Person> persons = new LinkedList<Person>();

// добавляем persona в список и получим объект LinkedListNode<Person>, в котором хранится имя Tom

LinkedListNode<Person> tom = persons.AddLast(new Person() { Name = "Tom" });

persons.AddLast(new Person() { Name = "John" });

persons.AddFirst(new Person() { Name = "Bill" });

Console.WriteLine(tom.Previous.Value.Name); // получаем узел перед томом и его значение

Console.WriteLine(tom.Next.Value.Name); // получаем узел после тома и его значение

Console.ReadLine();

}

}

class Person

{

public string Name { get; set; }

}

}

Результат работы программы представлен на рисунке А.3.

Рисунок А.3 - Результат использования списка LinkedList<T>

Листинг 5 - Пример использования словарей

using System;

using System.Collections.Generic;

namespace ConsoleApplication1

{

class UserInfo

{

// Метод, реализующий словарь

public static Dictionary<int, string> MyDic(int i)

{

Dictionary<int, string> dic = new Dictionary<int,string>();

Console.WriteLine("Введите имя сотрудника: \n");

string s;

for (int j = 0; j < i; j++)

{

Console.Write("Name{0} --> ",j);

s = Console.ReadLine();

dic.Add(j, s);

Console.Clear();

}

return dic;

}

}

class Program

{

static void Main()

{

Console.Write("Сколько сотрудников добавить? ");

try

{

int i = int.Parse(Console.ReadLine());

Dictionary<int, string> dic = UserInfo.MyDic(i);

// Получить коллекцию ключей

ICollection<int> keys = dic.Keys;

Console.WriteLine("База данных содержит: ");

foreach (int j in keys)

Console.WriteLine("ID -> {0} Name -> {1}",j,dic[j]);

}

catch (FormatException)

{

Console.WriteLine("Неверный ввод");

}

Console.ReadLine();

}

}

}

Результат работы программы представлен на рисунке А.4.

Рисунок А.4 - Пример использования словарей

Листинг 6 - Пример использования класса SortedSet<T>

using System;

using System.Collections.Generic;

namespace ConsoleApplication1

{

class Program

{

static void Main()

{

// Создадим два множества

SortedSet<char> ss = new SortedSet<char>();

SortedSet<char> ss1 = new SortedSet<char>();

ss.Add('A');

ss.Add('B');

ss.Add('C');

ss.Add('Z');

ShowColl(ss, "Первая коллекция: ");

ss1.Add('X');

ss1.Add('Y');

ss1.Add('Z');

ShowColl(ss1, "Вторая коллекция");

ss.SymmetricExceptWith(ss1);

ShowColl(ss,"Исключили разноименность двух множеств: ");

ss.UnionWith(ss1);

ShowColl(ss, "Объединение множеств: ");

ss.ExceptWith(ss1);

ShowColl(ss, "Вычитание множеств");

Console.ReadLine();

}

static void ShowColl(SortedSet<char> ss, string s)

{

Console.WriteLine(s);

foreach (char ch in ss)

Console.Write(ch + " ");

Console.WriteLine("\n");

}

}

}

Результат работы программы представлен на рисунке А.5.

Рисунок А.5 - Пример использования класса SortedSet<T>

Листинг 7 - Пример применения параллельных коллекций

using System;

using System.Collections.Concurrent;

using System.Threading;

using System.Threading.Tasks;

namespace ConsoleApplication1

{

class Program

{

static BlockingCollection<int> bc;

static void producer()

{

for (int i = 0; i < 100; i++)

{

bc.Add(i * i);

Console.WriteLine("Производится число " + i * i);

}

bc.CompleteAdding();

}

static void consumer()

{

int i;

while (!bc.IsCompleted)

{

if (bc.TryTake(out i))

Console.WriteLine("Потребляется число: " + i);

}

}

static void Main()

{

bc = new BlockingCollection<int>(4);

Task Pr = new Task(producer);

Task Cn = new Task(consumer);

Pr.Start();

Cn.Start();

try

{

Task.WaitAll(Cn, Pr);

}

catch (Exception ex)

{

Console.WriteLine(ex);

}

finally

{

Cn.Dispose();

Pr.Dispose();

bc.Dispose();

}

Console.ReadLine();

}

}

}

Рисунок А.6 - Применения параллельных коллекций

Листинг 8 - Пример использования перечислителей

using System;

using System.Collections.Generic;

namespace ConsoleApplication1

{

class Program

{

static void Main()

{

List<int> arr = new List<int>();

Random ran = new Random();

for (int i = 0; i < 10; i++)

arr.Add(ran.Next(1, 20));

// Используем перечислитель

IEnumerator<int> etr = arr.GetEnumerator();

while (etr.MoveNext())

Console.Write(etr.Current + "\t");

Console.WriteLine("\n Повторный вызов перечислителя: \n");

// Сбросим значение и вновь исользуем перечислитель

// для доступа к коллекции

etr.Reset();

while (etr.MoveNext())

Console.Write(etr.Current + "\t");

Console.ReadLine();

}

}

}

Результат работы программы с использованием перечислителей представлен на рисунке А.7

Рисунок А.7 - Использование перечислителей

Листинг 9 - Пример применения интерфейсов IEnumerator и IEnumerable

using System;

using System.Collections;

namespace ConsoleApplication1

{

class MyInt : IEnumerable, IEnumerator

{

int[] ints = { 12, 13, 1, 4 };

int index = -1;

// Реализуем интерейс IEnumerable

public IEnumerator GetEnumerator()

{

return this;

}

// Реализуем интерфейс IEnumerator

public bool MoveNext()

{

if (index == ints.Length - 1)

{

Reset();

return false;

}

index++;

return true;

}

public void Reset()

{

index = -1;

}

public object Current

{

get

{

return ints[index];

}

}

}

class Program

{

static void Main()

{

MyInt mi = new MyInt();

foreach (int i in mi)

Console.Write(i+"\t");

Console.ReadLine();

}

}

}

Результат работы программы с использованием интерфейсов IEnumerator и Ienumerable представлен на рисунке А.8

Рисунок А.8 - Использование интерфейсов IEnumerator и Ienumerable

Листинг 10 - Пример использования именованного итератора

class Book

{

public Book(string name)

{

this.Name=name;

}

public string Name { get; set; }

}

class Library : IEnumerable

{

private Book[] books;

public Library()

{

books = new Book[] { new Book("Отцы и дети"), new Book("Война и мир"),

new Book("Евгений Онегин") };

}

public int Length

{

get { return books.Length; }

}

public Book this[int index]

{

get

{

return books[index];

}

set

{

books[index] = value;

}

}

public IEnumerable GetBooks(int max)

{

for (int i = 0; i < max; i++)

{

if (i == books.Length)

{

yield break;

}

else

{

yield return books[i];

}

}

}

}

Размещено на Allbest.ur


Подобные документы

  • Разработка и реализация универсальной программной коллекции для абстрактного типа данных (АТД) "Простой статический граф" с графическим интерфейсом. Особенности использование ее для решения задач для неориентированных, ориентированных и взвешенных графов.

    курсовая работа [502,3 K], добавлен 24.09.2013

  • Совокупность программных и аппаратных средств, обеспечивающих взаимодействие пользователя с компьютером. Классификация интерфейсов, текстовый режим работы видеоадаптера. Функции текстового режима. Реализация пользовательского интерфейса в BORLAND C++.

    лабораторная работа [405,1 K], добавлен 06.07.2009

  • Стандартный интерфейс IEC 625-1 для программируемых приборов. Логическая организация интерфейса. Протокол сигналов для установления связи по магистрали IEC. Условия функционирования приборов в системе. Коды и форматы, физическая реализация интерфейса.

    контрольная работа [102,4 K], добавлен 23.01.2014

  • Основные понятия, применяемые при описании интерфейсов, их классификация. Обзор применяемых в компьютерной технике интерфейсов по их характеристикам и области применения. Описание и основные характеристики интерфейсов IDE, IEEE-1394, HDMI 1.4 и SATA.

    курсовая работа [183,3 K], добавлен 25.04.2012

  • Анализ графических пользовательских интерфейсов современных систем оптимизации программ. Создание математической модели и алгоритма системы управления СБкЗ_ПП, ее архитектурно-контекстная диаграмма. Техническая документация программного средства.

    дипломная работа [1,1 M], добавлен 18.04.2012

  • Сущность и предназначение последовательных интерфейсов. Формат асинхронной и синхронной посылки. Функциональные возможности и схема соединения по интерфейсу RS-232C. Назначение сигналов интерфейса. Понятие, конфигурирование и использование СОМ-портов.

    контрольная работа [175,2 K], добавлен 09.11.2010

  • Вставка объекта, созданного в другом графическом редакторе. Рисование в документе. Вставка рисунка из коллекции Clipart и размещение поверх него текста. Создание визитной карточки. Создание визитной карточки, заключенной в рамку из коллекции Clipart.

    лабораторная работа [555,8 K], добавлен 10.03.2007

  • Понятие социальной сети, определение основных целей и задач ее создания, распространенность и значение в современном обществе. Модели влияния в социальных сетях. Выбор средств проектирования и программная реализация, разработка и реализация интерфейса.

    дипломная работа [1,5 M], добавлен 11.09.2012

  • Основные приемы работы с классами и объектами. Перегрузка функций и операторов. Массивы объектов. Реализация одиночного наследования. Множественное наследование. Виртуальные функции. Шаблоны: понятие и функциональные особенности, свойства и применение.

    методичка [1,1 M], добавлен 16.04.2012

  • Аппаратные характеристики системы, использованной для разработки информационного ресурса "Сортировка слиянием". Проектирование логической и физической структуры ресурса, реализация его интерфейса. Основные функции программы, ее тестирование и отладка.

    курсовая работа [2,1 M], добавлен 26.11.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.