Найти в Дзене
JuniorCoder

Использование преимуществ кода F# в коде на C#

Здравствуй, читатель. Я хотел бы рассказать, как использовать преимущества разных языков программирования среды dotnet в одном проекте. Рассматривать будем одно нововведение, а именно реализацию интерфейсов с разными универсальными экземплярами ( в версии F # 5.0).
Это «фича» может сделать код более коротким и гибким в работе. Сразу стоит сказать, что с F # я знаком слабо, поэтому стиль написания

Здравствуй, читатель. Я хотел бы рассказать, как использовать преимущества разных языков программирования среды dotnet в одном проекте. Рассматривать будем одно нововведение, а именно реализацию интерфейсов с разными универсальными экземплярами ( в версии F # 5.0).
Это «фича» может сделать код более коротким и гибким в работе. Сразу стоит сказать, что с F # я знаком слабо, поэтому стиль написания кода на нём может быть не привычен для опытного разработчика.

Начнём.
С формулируем задачу:
Разработать библиотеку классов, которая должна следить за изменением температуры и выводить информацию о том, что изменение произошло. Предусмотреть возможность вывода значения температуры в разных единицах измерения.

Я предложу свою реализацию с использованием F# .

Для начала создадим свои структуры данных, которые будут хранить в себе значение температур, но в разных единицах измерениях.
Создадим библиотеку классов для F# .

Cтруктура проекта на F# .
Cтруктура проекта на F# .

В ней несколько файлов: Struct и Temperature . В файле Struct определены структуры данных, с которыми будет производится некоторые действия. В файле Temperature заложена логика взаимодействия со структурами.

Структуры, описывающие разные единицы измерения температуры.
Структуры, описывающие разные единицы измерения температуры.

Структуры есть. Но стойте, везде присутствует одно и тоже поле value . К тому же, не очень будет удобно работать со структурами в ситуациях, когда точно не известен её тип. Но F # мультипарадигмальный язык программирования. Поэтому перепишем чуть-чуть структуры.

Измененный код структур единиц измерения температуры.
Измененный код структур единиц измерения температуры.

Вот. Уже другое дело. Теперь мы сможем работать с структурами как с интерфейсом. Привет паттерн «Стратегия».

Далее перейдём к файлу Temperature .
В нём как раз и будет использоваться обобщенный интерфейс и класс с разными его реализациями.

Сам интерфейс будет довольно простым.

Интерфейс IConvertable.
Интерфейс IConvertable.

То есть всего 3 метода, которые в зависимости от типа ` T будут конвертировать значение в другую структуру.

Теперь создадим класс и реализуем этот интерфейс с разными типами данных. Получилось что-то вроде такого:

Класс Temperature.
Класс Temperature.

И так, что тут происходит.
Создался класс Temperature с одним полем value типа ITemperature (общего интерфейса наших структур) и конструктором, принимающим объект ITemperature (по сути, нашу структуру) и записывает её в своё поле.

А также 3 раза реализовался интерфейс IConvertable от всех наших типов структур ( C , F , K ), которые были созданы нами ранее в файле Struct . И сразу определена логика работы каждого метода этого интерфейса. Честно скажу, такая реализация очень упрощается работу и уменьшает объём кода.

Теперь создадим библиотеку классов, но уже на C # . По факту это лишнее, но мне хотелось проверить, как сгенерированные классы для F # будут вести себя в проекте на C #

И так, добавился проект на C # .

Структура проекта на C # .
Структура проекта на C # .

EventBroker – это своеобразный менеджер вызова событий. Он представляет из себя статичный класс.

EventHandlerMonitorTemperature – класс для передачи информации событий в классы, которые подписались на изменения.

MonitorTemperature – класс, работающий с библиотекой на F# .

Полный код и реализацию можно посмотреть в моём репозитории на Github .

Самое главное, где использовалась наша обсуждаемая «фича»:

Использование интерфейса IConvertable от разных типов структур.
Использование интерфейса IConvertable от разных типов структур.

Это конструктор класса EventHandlerMonitorTemperature, в который приходит объект класса Temperature из нашей библиотеки на F # . В нём достаём ссылку на структуру ( structTemp ). И далее используя Pattern Matching определяем её тип. В каждом « case » создаём переменную типа структуры, которая нас интересует и дальше просто вызываем уже реализованные методы в классе Temperature . По факту класс Temperature приводится к интерфейсу IConvertable<”наша структура”> и вызывается тот метод с той реализацией, которая соответствует этому интерфейсу.

Для проверки создадим небольшое консольное приложение. Код будет следующим:

Код консольного приложения для проверки конвертации единиц измерения температур.
Код консольного приложения для проверки конвертации единиц измерения температур.

В теле метода Main используется 3 метода класс EventBroker , которые записывают температуру кипения в разных единицах измерения.

Результатом выполнения кода станет следующее:

Результат работы консольного приложения.
Результат работы консольного приложения.

То есть все наши значения были корректно переведены в те единицы измерения, которые нас интересовали.

Я только начал погружаться в мир F # и хочу сказать одно: он очень неплох. Его стоит использовать в «продакшене» и можно использовать в связке с C # без всяких проблем, используя преимущества этих языков.