Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Создание пользовательских обобщенных классов

Читайте также:
  1. III. Употребление артиклей в сочетаниях классовых существительных с уточняющим и описательным определениями.
  2. Анализ школьных учебников истории ОС «Школа 2100» для старших классов.
  3. Бесклассовая адресация CIDR и маски переменной длины VLSM
  4. Бесклассовый общественный строй с единой общенародной собственностью на средства производства, полным социальным равенством всех членов.
  5. Ввод исходных графических данных в персональный компьютер. Создание компьютерной геометрической модели объекта
  6. Воссоздание земных поселений
  7. Воссоздание земных поселений.

Обобщенный класс определяется так же, как и нормальный, но с объявлением обобщенного типа. Обобщенный тип затем может быть использован внутри класса как тип поля-члена или как тип параметров метода:

 

public class MyGeneric<T>

{

private T member;

public void Method(T obj)

{ }

}

 

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

Ниже мы переделаем класс DocumentManager, который был определен ранее. Попытаемся построить класс, достаточно гибкий, чтобы он поддерживал не только тип Document. Вот новая версия класса:

 

public class DocumentManager<T>: IDocumentManager<T>

{

private readonly Queue<T> documentQueue = new Queue<T>();

public void AddDocument(T doc)

{

lock (this)

{

documentQueue.Enqueue(doc);

}

}

public T GetDocument()

{

T doc = default(T);

lock (this)

{

doc = documentQueue.Dequeue();

}

return doc;

}

public bool IsDocumentAvailable

{

get

{

return (documentQueue.Count > 0)? true: false;

}

}

}

Ранее класс Document использовался классом DocumentManager. Теперь мы объявили его как использующий тип Т. DocumentManager стал настолько гибким, что теперь позволяет использовать в качестве Т любой тип. Этот тип может применяться с переменными внутри класса. Как здесь показано, обобщенный тип также может быть применен при использовании обобщенного типа, такого как Queue<T>. Тот же тип, что служит параметром при создании экземпляра DocumentManager<T>, применяется для создания экземпляра Queue<T>:

 

public class DocumentManager<T>: IDocumentManager<T>

{

private readonly Queue<T> documentQueue = new Queue<T>();

Методы AddDocument() и GetDocument() определяют Т в качестве типа параметра и типа возврата:

public void AddDocument(T doc)

{

//....

}

public T GetDocument()

{

//.

}

 

Обобщенному типу невозможно присвоить null. Причина в том, что вместо него может быть подставлен тип значения, не допускающий null, a null допускаются только со ссылочными типами. Чтобы обойти эту проблему, можно воспользоваться ключевым словом default. Оно позволяет присваивать null ссылочным типам и 0 — типам значений.

 

T doc = default(T);

 

Проведем изменение класса ProcessDocuments для того чтобы сделать его обобщенным. Поскольку ProcessDocuments вызывает методы класса Document, для него должна использоваться конструкция where, специфицирующая методы и свойства, которые должны присутствовать у обобщенного типа. Конструкция where может требовать от обобщенного типа реализации интерфейса или наследования от определенного базового класса.

Новая версия ProcessDocuments будет независимой от класса Document, равно как и от класса DocumentManager. Это достигается определением интерфейсов IDocument и IDocumentManager<T>, которые определяют методы и свойства, используемые ProcessDocuments<T, U>.

Интерфейс IDocument определяет свойства Title и Content, доступные только для чтения:

 

public interface IDocument

{

string Title

{

get;

}

string Content

{

get;

}

}

 

Ранее созданный нами класс Document теперь реализует интерфейс IDocument:

 

public class Document: IDocument

{ }

 

IDocumentManager<T> — это обобщенный интерфейс. Тип Т для методов этого интерфейса от случая к случаю может быть реализован по-разному:

 

public interface IDocumentManager<T>

{

void AddDocument(T doc);

T GetDocument();

bool IsDocumentAvailable

{

get;

}

}

 

Теперь класс DocumentManager<T> реализует интерфейс
IDocumentManager<T>. Обобщенный тип для интерфейса определен классом DocumentManager<T>:

 

public class DocumentManager<T>: IDocumentManager<T>

{ }

 

Теперь изменим класс ProcessDocuments так, чтобы он использовал два обобщенных типа: TDocument и TDocumentManager. Первая конструкция where утверждает, что тип TDocument должен реализовывать интерфейс
IDocument. Одним из типов, который может быть подставлен вместо
TDocument, является Document, потому что этот класс реализует интерфейс IDocument. Однако и любой другой класс, реализующий интерфейс IDocument, также может быть подставлен вместо TDocument. Конструкция where для типа TDocumentManager определяет, что этот тип должен реализовывать интерфейс IDocumentManager<TDocument>. Поэтому в случае подстановки Document вместо TDocument TDocumentManager должен быть классом, реализующим интерфейс IDocumentManager<Document>.

Обобщенные типы TDocument и TDocumentManager теперь используются в реализации:

 

public class ProcessDocument<TDocument, TDocumentManager>

where TDocument: IDocument

where TDocumentManager: IDocumentManager<TDocument>

{

private TDocumentManager documentManager;

public static void Start(TDocumentManager dm)

{

new Thread(new ProcessDocument<TDocument,

TDocumentManager>(dm).Run).Start();

}

protected ProcessDocument (TDocumentManager dm)

{

documentManager = dm;

}

protected void Run()

{

while (true)

{

if (documentManager.IsDocumentAvailable)

{

TDocument doc = documentManager.GetDocument();

Console.WriteLine("Обработка документа {0}",

doc.Title);

}

Thread.Sleep(new Random().Next(10));

}

}

}

 

В методе Main() DocumentManager теперь инициируется классом
Document. Статский метод Start() класса ProcessDocuments вызывается с передачей класса Document в качестве параметра TDocument, и класса
DocumentManager<Document> в качестве параметра TDocumentManager:

 

class Program

{

static void Main(string[] args)

{

DocumentManager<Document> dm = new DocumentManager<Document>();

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<Document, DocumentManager<Document>>.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.7.

 

а) начало вывода б) окончание вывода

Рис. 7.7. Добавление и извлечение из очереди документов для обобщенных классов

В том случае, если нужно будет использовать новые объекты обобщенных типов при создании экземпляров обобщенных классов, конструкция where может быть расширена добавлением ограничения конструктора new(). Это ограничение конструктора говорит о том, что в обобщенном типе должен присутствовать конструктор по молчанию:

 

public class MyClass<T>

where T: IFoo, new() { //-..

 

В.NET ограничения конструктора могут указывать на необходимость наличия только конструктора по умолчанию. Невозможно определить ограничение конструктора для других конструкторов.


Дата добавления: 2015-07-07; просмотров: 124 | Нарушение авторских прав


Читайте в этой же книге: Повторное использование двоичного кода | Обзор обобщенных коллекций | Поиск элементов | Сортировка | Обобщенные делегаты |
<== предыдущая страница | следующая страница ==>
Преобразования типов| Обобщенные методы

mybiblioteka.su - 2015-2024 год. (0.015 сек.)