Обобщения (generics) необходимы в тех случаях, когда мы не можем заранее знать тип данных, который будем использовать. Они есть во многих языках программирования.
Пример использования обобщений
Представим ситуацию, что заказчик дал нам работу в виде создания ПО для работы с продажей различных видов товаров, по различной цене.
Все мы знаем (а может предстоит узнать), что заказчики очень изменчивые люди в плане своих проектов. Сегодня он скажет сделать цену в виде целого числа, а завтра ему понадобятся еще и копейки в виде дробной.
Что делать в таком случае? Переписывать логику? Ведь если мы изменим тип данных, то вся программа сломается и будет куча ошибок из-за несоответствия типов в классе "продажи".
Выход из данной ситуации есть - и то это шаблоны!
Пример реализации
Давайте рассмотрим приведенный выше пример подробнее и реализуем его на практике
Реализация без шаблонов
Начнём с того, что мы не знаем, про обобщения и реализуем поставленную задачу без них.
Опишем поставленную задачу:
Программа имеет возможность продажи различных продуктов по заданной цене , например “хлеб” за 45 рублей. Исходя из этого можно понять, что мы имеем некий класс, назовем его Product , который имеет поля - Name (наименование продукта ), Price (цена продукта) и один метод Sell (метод продажи). (Рис.1)
Попробуем использовать написанный код
Создадим продукт , который будет являться хлебом , стоить он будет 45 рублей ( целое число), затем вызовем метод Sell() (Рис.2)
Запустим программу и увидим , что мы продали хлеб за 45 рублей. (Рис.3)
Проблема, которая может возникнуть
А теперь представим , что заказчик сообщил о том, что цену на хлеб необходимо указать с копейками.
У нас есть (пока что) лишь один выход из данной ситуации - изменить всю логику класса , задав тип данных вместо целого числа (int) - дробное (float). Действительно, если проделать данные действия , то заказчик будет удовлетворён , но что если логика продажи будет очень большой и нам из-за прихоти заказчика придется все переписывать? так как лично я достаточно ленивый человек - делать этого мне не очень будет хотеться.
Теперь вот как раз таки обобщения выступают нам как «ангел хранитель», который поможет нам спасти себя от рутинной работы обновления логики каждый раз, когда заказчик будет менять свои запросы.
Использование обобщений
Угловые скобки в описании class Product<T> указывают, что класс является обобщенным, а тип T, заключенный в угловые скобки, будет использоваться этим классом. Необязательно использовать именно букву T, это может быть и любая другая буква. Причем сейчас на этапе написания кода нам неизвестно, что это будет за тип, это может быть любой тип. Поэтому параметр T в угловых скобках еще называется универсальным параметром, так как вместо него можно подставить любой тип.
Изменим структуру нашего класса с использованием обобщения (Рис.4)
Теперь мы увидим ошибку в методе Main (Рис.5)
Данная ошибка появилась из-за того, что мы не используем int как было раньше, теперь мы используем обобщение с типом T , следовательно нам необходимо, изменить объявление объекта класса Product, следующим образом (Рис.6)
В угловых скобках мы указали тип данных double , исходя из этого цена продукта T Price в классе Product, грубо говоря подставит тип данных double вместо T и в последующем будет его использовать.
Запустим программу и увидим, что мы продали товар за 45.5 рублей (Рис.7)
Теперь, мы можем для цены Price использовать любой тип данных для каждого нового объекта класса, например создадим новый объект и в качестве T укажем тип данных string
Создадим объект класса Product<string> назовем его milk и укажем название name - "Молоко", а цену Price - "Нет в наличии. 0 рублей", затем вызовем метод Sell (Рис.8)
Запустим программу и увидим, что все работает (Рис.9)
В рамках такого небольшого примера, трудно 'разойтись', но думаю в целом стало немного понятнее.
Также ярким примером использования шаблонов можно назвать всем известный класс List<T> , данный класс не знает с каким типом данных он будет работать заранее и при передаче в качестве T любого типа данных, логика не поломается. А вот если бы класс шаблоны не использовал, то для каждого нового типа данных пришлось бы создавать копию класса с практически идентичной логикой, но просто переделанной под другой тип
Вывод
Обобщения присутствует во многих языках программирования. Шаблонизация используется фактически во всех динамических структурах языка C# (списки, очереди, стеки и т. д). Знание этого инструмента программирование поможет вам создавать более универсальные структуры и алгоритмы