Главная · Карта сайта · Поиск · Статьи · Компьютерные курсы · Обучающие программы · Открытые проекты · Веб-программирование · Создание интернет-сайта · Полезные ссылки · Глоссарий · Контакты · Декабрь 06 2016 22:53:48
Последнее опубликованное

Что такое Model-View-Controller
Pattern Model-View-Controller

Как создать свой веб-сайт
Как создать свой сайт в интернете

Разное
Статистика

Программирование на C#. Универсальный класс


[Назад] [Следующая страница]

3.2. Создание универсального типа

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

using System;
using System.Collections.Generic;  
namespace CSharpQuickGuide
{
    //Интерфейс формирования графического представления
    //пространственных данных
    public interface IDrawContext { }
    //Коллекция геометрических объектов
    public class GeometrySet<TItem, TBaseContainer> 
        //должна реализовать стандартные интерфейсы коллекций BCL:
        : IEnumerable<TItem>, ICollection<TItem>
        where TItem : Geometry2D //TItem обязан быть производным от Geometry2D
        where TBaseContainer : IEnumerable<TItem>, ICollection<TItem>, new()
    {
        //Контейнер элементов коллекции также обязан
        //поддерживать стандартные интерфейсы BCL и иметь
        //конструктор по умолчанию (баз параметров). Последнее 
        //ограничение добавляется с использованием ключевого слова new()
        //в списке ограничений после ключевого слова where (см. выше)
        private TBaseContainer m_Container;
        //Конструктор по умолчанию
        public GeometrySet()
        {
            //Наличие у типа TBaseContainer конструктора по умолчанию
            //гарантирует ограничение new()
            m_Container = new TBaseContainer(); 
        }
        //Виртуальный метод 'рисования' пространственных данных
        public virtual void Draw<TContext>(TContext _context)
            where TContext : class, IDrawContext
        { throw new NotImplementedException(); }

        //Реализация стандартных интерфейсов BCL
        //(IEnumerable<TItem>, ICollection<TItem>)
        //здесь не приводится
    }
}

Как уже упоминалось в предыдущем разделе, использование стандартных интерфейсов BCL при проектировании новых классов позволит использовать специальные конструкции языка C# (foreach) при их обработке. Также, мы вправе рассчитывать на то, что классы BCL, предназначенные для обработки элементов стандартных коллекций, смогут адекватно обрабатывать и нашу коллекцию. Ну и наконец, есть в BCL такой замечательный пользовательский элемент управления PropertyGrid, который умеет работать с данными любого объекта, используя метаданные его класса. Он с удовольствием предоставит вам свои услуги по редактированию вашей коллекции средствами GUI, но только в том случае, если тип вашей коллекции реализует стандартные интерфейсы пространства имен System.Collections.Generic.

Может показаться, что приводимым примерам свойственна некоторая надуманность. Может это и так, но здесь я преследую скорее цель продемонстрировать на каждом отдельном примере как можно больше возможностей C#, нежели представить идеально спроектированное решение поставленной по легенде задачи. Пусть наш класс-коллекция, в дополнение к стандартным интерфейсам, реализует логику формирования графического представления своего содержимого посредством специализированного интерфейса IDrawContext. Реализовывать этот интерфейс может класс вывода графики на экран, на принтер или в файл. Экземпляр такого сервиса передается в качестве параметра методу Draw() (см. пример кода). В общем, интерфейс IDrawContext - это что-то вроде GDI или GDI+

Graphical Device Interface, GDI - часть ядра операционной системы Windows, отвечающей за вывод графики на экран и другие устройства.

Возможно, метод Draw() нашей коллекции должен вызывать аналогичные методы объектов – элементов коллекции, а возможно и сам должен что-то делать. В данном контексте это не важно, а сам программный код вывода графики по понятным причинам здесь не приводится. Пример представлен слева.

В нашем примере класс GeometrySet параметризуется двумя типами: типом элемента коллекции (TItem) и типом базового контейнер (TBaseContainer). После ключевого слова where перечислены ограничения, которые мы накладываем на типы-параметры: кто должен являться их базовым классом, какие интерфейсы они должны реализовывать, должны ли реализовывать открытый конструктор по умолчанию (new()) и так далее. Если вы хотите, чтобы тип-параметр был только классом, либо структурой, то используйте синтаксис where с ключевыми словами class или struct соответственно. Метод Draw() использует свой собственный тип-параметр TContext, на который накладывает собственные ограничения: чтобы TContext был классом, реализующим интерфейс IDrawContext.

Я использовал в примере дополнительный параметр TBaseContainer для того чтобы во-первых: указать на возможность определять несколько типов – параметров; во-вторых: заострить внимание читателя на том, что BCL содержит несколько стандартных контейнеров в пространстве имен System.Collections.Generic, реализующих подобный набор интерфейсов, но оптимизированных для разного рода операций (поиск, изменение коллекции, сортировка), например: List<T>, LinkedList<T>, SortedList<T>. Какую именно реализацию контейнера использовать, будет определяться контекстом операции. Перейдя по указанной ссылке, вы попадете в раздел, описывающий виды и особенности линейных структур данных, в конце которого сделан обзор, какие классы BCL для каких целей оптимизированы.

Пример создания экземпляра нашей коллекции приведен ниже.

using System;
using System.Collections.Generic;
namespace CSharpQuickGuide
{
    static class Application
    {
        static void Main()
        {
            GeometrySet<Label, LinkedList<Label>> _set = new GeometrySet<Label, LinkedList<Label>>();    
        }
    }
}


[Назад] [Следующая страница]

Компьютерные курсы и курсы программирования
Основы программирования

Курс для начинающих программистов на C# и VB.NET.

SQL 25™

Построение SQL запросов и работа с базой данных.

C# Quick Guide™

Программирование на C#. Краткое руководство.

RegEx

Применение регулярных выражений.

Plug-in архитектура

Примеры программной Plug-in архитектуры.

XML и его расширения

Язык разметки XML и его расширения с примерами.

HTML и разметка гипертекста

Языки HTML, XHTML и CSS с примерами разметки.

Основы веб-дизайна

Основы веб-дизайна: решения типовых задач верстки.

Программирование на PHP

Руководство по программированию на PHP для начинающих.

Справочные материалы

Шаблоны проектирования
Каталог шаблонов проектирования программных компонентов.

Рефакторинг кода
Каталог приемов рефакторинга программного кода.

Гость
Имя

Пароль



Забыли пароль?
Запросите новый здесь
.
Coding Craft. Все права защищены © 2011. Проект Инициативного Народного Фронта Образования - ИНФО-проект.