Читайте также:
|
|
С помощью метода ConvertAll() класса List<T> все элементы коллекции могут быть преобразованы в другой тип. Метод ConvertAll() использует делегат Converter, определенный следующим образом:
public sealed delegate TOutput Converter<TInput, TOutput>(TInput from);
При преобразовании используются обобщенные типы TInput и TOutput. ТInput — это аргумент метода делегата, a TOutput — возвращаемый тип.
В следующем примере все элементы типа Student должны быть преобразованы в тип Person. В то время как тип Student включает полное имя и номер группы, тип Person включает имя (firstname) и фамилию (lastname). При таком преобразовании номер группы может быть проигнорирована, но имя нужно преобразовать в firstname и lastname:
class Person
{
private string firstname;
private string lastname;
public Person(string firstname, string lastname)
{
this.firstname = firstname;
this.lastname = lastname;
}
public override string ToString()
{
return firstname+ " "+lastname;
}
}
Преобразование выполняется вызовом метода students.ConvertAll<Person>. Параметр этого метода определен, как анонимный метод с аргументом типа Student, возвращающий значение типа Person. В реализации анонимного метода создается и возвращается новый объект Person. Свойство FullName объекта Student преобразуется в firstname и
lastname:
List<Person> persons = students.ConvertAll<Person>(delegate(Student st)
{int ixSeparator = st.FullName.LastIndexOf(" ") + 1;
string firstname = st.FullName.Substring(ixSeparator,
st.FullName.Length - ixSeparator);
string lastname = st.FullName.Substring(0,
ixSeparator - 1);
return new Person(firstname, lastname);};
В результате такого преобразования получается список конвертированных объектов Person — то есть List<Person> (рис. 7.5).
Рис. 7.5. Результаты преобразования класса Student в класс Person
Использование класса Queue<T>
Класс Queue<T> обладает той же функциональностью, что и класс Queue — то есть это просто обобщенная версия очереди. Элементы обрабатываются по алгоритму «первым пришел — первым обслужен» (FIFO).
В качестве примера применения класса Queue<T> рассмотрим приложение управления документацией. Один поток управления будет добавлять документы в очередь, а второй — извлекать из очереди и обрабатывать.
Элементы, сохраняемые в очереди, будут относиться к типу Document. Класс Document состоит из заголовка и содержимого:
public class Document
{
private string title;
private string content;
public string Title
{
get { return title; }
}
public string Content
{
get { return content; }
}
public Document(string title, string content)
{
this.title = title;
this.content = content;
}
}
Класс DocumentManager — надстройка над Queue<T>. Класс
DocumentManager определяет, как обрабатываются документы: добавляются в очередь методом AddDocument() и извлекаются методом
GetDocument().
Внутри метода AddDocument() документ добавляется в конец очереди с помощью метода Enqueue(). Первый документ из очереди читается методом Dequeue() внутри GetDocument(). Поскольку к DocumentManager могут иметь одновременный доступ несколько потоков параллельно, доступ к очереди блокируется оператором lock.
IsDocumentAvailable — свойство булевского типа, доступное только для чтения; оно возвращает true, если в очереди есть документы и false — в противном случае:
public class DocumentManager
{
private readonly Queue<Document> documentQueue = new Queue<Document>();
public void AddDocument(Document doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
public Document GetDocument()
{
Document doc = null;
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
public bool IsDocumentAvailable
{
get
{
return documentQueue.Count > 0;
}
}
}
Класс ProcessDocuments обрабатывает документы из очереди в отдельном потоке. Единственный его метод, который доступен извне — это Start(). В теле метода Start() создается экземпляр нового потока. Объект
ProcessDocuments создается для запуска потока, а метод Run() определен как стартовый метод потока. ThreadStart — делегат, который ссылается на метод, подлежащий запуску в потоке. После создания объекта Thread поток запускается вызовом Thread.Start().
Внутри метода Run() класса ProcessDocuments определен бесконечный цикл. В этом цикле свойство IsDocumentAvailable используется для проверки наличия документа в очереди. Если в очереди есть документ, то документ извлекается DocumentManager и обрабатывается. В данном случае вся обработка сводится к отображению информации на консоли. В реальном приложении документ может быть записан в файл, сохранен в базе данных либо отправлен по сети.
public class ProcessDocument
{
private DocumentManager documentManager;
public static void Start(DocumentManager dm)
{
new Thread(new ProcessDocument(dm).Run).Start();
}
protected ProcessDocument(DocumentManager dm)
{
documentManager = dm;
}
protected void Run()
{
while (true)
{
if (documentManager.IsDocumentAvailable)
{
Document doc = documentManager.GetDocument();
Console.WriteLine("Обработка документа {0}", doc.Title);
}
Thread.Sleep(new Random().Next(20));
}
}
}
В методе Main() приложения создается объект DocumentManager, создается 100 документов с номерами от 0 до 99 и запускается поток обработки документов. Затем создается 10 документов с номерами от 100 до 110, и все они добавляются в DocumentManager. В реальном приложении документы могут поступать от Web-службы.
class Program
{
static void Main(string[] args)
{
DocumentManager dm = new DocumentManager();
for (int i = 0; i < 100; i++)
{
Document doc = new Document("Документ " + i.ToString(), "Содержание " + i.ToString());
dm.AddDocument(doc);
Thread.Sleep(new Random().Next(10));
}
Console.WriteLine("\nФормирование документов завершено\n");
ProcessDocument.Start(dm);
for (int i = 101; i < 110; i++)
{
Document doc = new Document("Документ "+i.ToString(), "Содержание "+i.ToString());
dm.AddDocument(doc);
Console.WriteLine("Добавленный документ {0}", doc.Title);
Thread.Sleep(new Random().Next(20));
}
}
}
При запуске приложения документы добавляются и извлекаются из очереди, как показано на рис. 7.6.
а) начало вывода | б) окончание вывода |
Рис. 7.6. Добавление и извлечение из очереди документов
Дата добавления: 2015-07-07; просмотров: 130 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Сортировка | | | Создание пользовательских обобщенных классов |