Произвести и поставить символы от А до Z.



static void Producer() {

for (char ch = 'A'; ch <= 'Z'; ch++) {

bc.Add(ch);

Console.WriteLine("Производится символ " + ch);

}

bc.CompleteAdding();

}

 

Потреблять символы до тех пор, пока их будет производить поставщик.

static void Consumer() {

char ch;

while(!bc.IsCompleted) {

If(bc.TryTake(out ch))

Console.WriteLine("Потребляется символ " + ch);

}

}

 

static void Main() {

Использовать блокирующую коллекцию,

Ограниченную 4 элементами,

bc = new BlockingCollection<char>(4);

 

Создать задачи поставщика и потребителя.

Task Prod = new Task(Producer);

Task Con = new Task(Consumer);

Запустить задачи.

Con.Start();

Prod.Start();

Ожидать завершения обеих задач,

try {

Task.WaitAll(Con, Prod);

} catch(AggregateException exc) {

Console.WriteLine (exc);

} finally {

Con.Dispose();

Prod.Dispose();

bc.Dispose();

}

}

}

 

Этот вариант программы дает такой же результат, как и предыдущий. Главное его отличие заключается в том, что теперь метод Producer() может производить и поставлять сколько угодно элементов. С этой целью он просто вызывает метод CompleteAdding(), когда завершает создание элементов. А метод Consumer() лишь "потребляет" произведенные элементы до тех пор, пока свойство IsCompleted не примет логическое значение true.

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

 

 

Сохранение объектов, определяемых пользователем классов, в коллекции

 

Ради простоты приведенных выше примеров в коллекции, как правило, сохранялись объекты встроенных типов, в том числе int, string и char. Но ведь в коллекции можно хранить не только объекты встроенных типов. Достоинство коллекций в том и состоит, что в них допускается хранить объекты любого типа, включая объекты определяемых пользователем классов.

Рассмотрим сначала простой пример применения класса необобщенной коллекции ArrayList для хранения информации о товарных запасах. В этом классе инкапсулируется класс Inventory.

 

// Простой пример коллекции товарных запасов.

using System;

using System.Collections;

 

class Inventory {

string name;

double cost;

int onhand;

 

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

 

public override string ToString() {

Return

String.Format("{0,-10}Стоимость: {1,6:C} Наличие: {2}",

name, cost, onhand);

}

}

 

class InventoryList {

static void Main() {

ArrayList inv = new ArrayList();

 

Добавить элементы в список.

inv.Add(new Inventory("Кусачки", 5.95, 3));

inv.Add(new Inventory("Отвертки", 8.29, 2));

inv.Add(new Inventory("Молотки", 3.50, 4));

inv.Add(new Inventory("Дрели", 19.88, 8));

 

Console.WriteLine("Перечень товарных запасов:");

foreach(Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

 

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

 

Перечень товарных запасов:

Кусачки Стоимость: $5,95 Наличие: 3

Отвертки Стоимость: $8,29 Наличие: 2

Молотки Стоимость: $3,50 Наличие: 4

Дрели Стоимость: $19,88 Наличие: 8

 

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

Для того чтобы сохранить объекты определяемых пользователем классов в типизированной коллекции, придется воспользоваться классами обобщенных коллекций. В качестве примера ниже приведен измененный вариант программы из предыдущего примера. В этом варианте используется класс обобщенной коллекции List<T>, а результат получается таким же, как и прежде.

 

// Пример сохранения объектов класса Inventory в

// обобщенной коллекции класса List<T>.

using System;

using System.Collections.Generic;

 

class Inventory {

string name; double cost; int onhand;

public Inventory(string n, double c, int h) {

name = n;

cost = c;

onhand = h;

}

 

public override string ToString() {

Return

String.Format("{0,-10}Стоимость: {1,6:C} Наличие: {2}",

name, cost, onhand);

}

}

 

class TypeSafelnventoryList {

static void Main() {

List<Inventory> inv = new List<Inventory>();

 

Добавить элементы в список.

inv.Add(new Inventory("Кусачки", 5.95, 3);)

inv.Add(new Inventory("Отвертки", 8.29, 2));

inv.Add(new Inventory("Молотки", 3.50, 4));

inv.Add(new Inventory("Дрели", 19.88, 8));

 

Console.WriteLine("Перечень товарных запасов:");

foreach (Inventory i in inv) {

Console.WriteLine(" " + i);

}

}

}

 

Данный пример отличается от предыдущего лишь передачей типа Inventory в качестве аргумента типа конструктору класса List<T>. А в остальном оба примера рассматриваемой здесь программы практически одинаковы. Это, по существу, означает, что для применения обобщенной коллекции не требуется никаких особых усилий, но при сохранении в такой коллекции объекта конкретного типа строго соблюдается типовая безопасность.

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

У рассматриваемой здесь программы имеется все же один не совсем очевидный недостаток: коллекция не подлежит сортировке. Дело в том, что в классах ArrayList и List<T> отсутствуют средства для сравнения двух объектов типа Inventory. Но из этого положения имеются два выхода. Во-первых, в классе Inventory можно реализовать интерфейс IComparable, в котором определяется метод сравнения объектов данного класса. И во-вторых, для целей сравнения можно указать объект типа IComparer. Оба подхода рассматриваются далее по очереди.

 

 


Дата добавления: 2019-02-12; просмотров: 242; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!