ИИ для программиста?
Так оно и работает https://dotnetfiddle.net/lSh3Aj
Но только при выполнении. А надо при компиляции. Придумать какие-то атрибуты чтоли для классов и их членов, чтобы при компиляции были какие-то проверки.
Вот можно сделать проверку типа внутри одного метода примерно так
Важное слово выделено...
Ну есть у вас класс конвертера. Добавили вы новый численный тип
Просто интересно, какой именно численный тип хотите добавить?
Именно поэтому он и не является расширяемым.
Ладно, тогда возвращаемся к кастомным типам от численных - смотрим на мой пример. Чем он плох, кроме того, что нет возможности заставить писать новую реализацию до выполнения. При этом нет громоздких конструкций, как у Срыва покровов, с интерфейсом и наследованием. И я чётко определяю набор типов, которые подходят - безо всяких лишних, которые могут вдруг реализовать интерфейс.
Единственное что, если начать наследоваться от моих этих типов, то выполнение уже будет не таким однозначным. Разве что закрыть их (sealed)?
Ну вот, при
public class C : B {}
и вызове
Process(new C());
выдаст
В
Т.е. он пытается привести к родителю и если возможно, то вызывает перегрузку для родителя. Т.е. отслеживать поддерживаемые типы точно, без возможности приведения, можно лишь закрыв их от наследования.
Method(Type1 param) => // do something
Method(Type2 param) => // do something
Method(object param) => NotSupportedException
Дед забыл принять таблетки
Удобно, чо. Вася создаст новый тип, своей метод не напишет и в рантайме вы получите исключение.
Зато не как у всех
И без интерфейсов.
Вася точно таким же образом может забыть унаследоваться от вашего интерфейса. Мы уже про ваш интерфейс перетёрли, что он также не гарантирует, что придёт левый тип, реализующий этот интерфейс. Т.е. внутри всё равно надо проверять на разрешённые типы.
Вобщем, всё сводится к тому, что что-то где-то должно Васе напоминать, иначе Вася точно когда-нибудь ошибётся. В идеале надо, чтобы в каком-то одном месте был один раз добавлен разрешённый тип, и далее все проверки проходили автоматически и желательно до выполнения программы. При этом это место должно быть максимально простым и понятным. Я вобщем-то всего, чего нужно добился просто перегрузкой методов, кроме последнего - "до выполнения программы". Ваш интерфейс решает эту проблему, но усугубляет все остальные.
При этом требование "до выполнения" может быть ослаблено или убрано, если есть тесты, которые собственно и выполняют код, но делают это не в продакшене, а когда не критично.
что он также не гарантирует, что придёт левый тип, реализующий этот интерфейс
ни один метод не даст 100% защиту. И как это левый или объект реализует конвертацию или нет. Если сказал, что реализует, никак не может быть левым.
Всё тоже самое можно сказать и о другой части. А если я сделаю перегрузку для левого объекта тогда как?
Главное, что всё логика, связанная с объектом, должна быть в объекте, а не растёрта по всему приложению.
Т.е. внутри всё равно надо проверять на разрешённые типы.
Зачем, а если и там забудешь или не то напишешь?
что он также не гарантирует, что придёт левый тип, реализующий этот интерфейсни один метод не даст 100% защиту.
Даст. Если у метода параметр только такого типа, то другой тип не придёт - будет ошибка компиляции. Ну, кроме приведения типа к родительскому.
Всё тоже самое можно сказать и о другой части. А если я сделаю перегрузку для левого объекта тогда как?
Это намеренное вредительство, а мы его не рассматриваем, т.к. от него защиты в рамках языка никакой нет. Намеренно не сделать новую перегрузку при создании нового типа, хотя знаешь, что надо и где надо делать эти перегрузки - это вредительство. А вот забыть сделать такие перегрузки или не знать, что их надо делать - такое бывает.
Скорее будет вариант, когда тип устарел и его можно удалить, и теперь надо удалить также все перегрузки, работающие с этим типом. Но тут уже давно есть помощь - проект не скомпилируется при отсутствующем типе, если он где-то используется.
Т.е. внутри всё равно надо проверять на разрешённые типы.Зачем, а если и там забудешь или не то напишешь?
Вот и вопрос - какой подход лучше, если ни один не идеальный? С интерфейсов и дженериком, или с перегрузкой? Первый вариант какой-то громоздкий, задействует две сущности.
Почему в Дотнете для числовых типов в конвертерных классах решили сделать под пару десятков перегрузок - на каждый числовой тип, вместо одного простого дженерика?
Вопрос был в размазывании логики типа по проекту. Методы расширения и парциальные классы делают это успешно.
Вообще, Сишарп называется мультипарадигмальным языком. Т.е. в нём есть место не одним сектантам всяких банд, робинзонов с островов и скачущих по сценам дедков с прошедшим ярким прошлым. ))) Где-то люди всё сваливают в одно место и не дают разбредаться логике, а где-то делают прямо наоборот, ещё и всякими микросервисами шлифуют.
Почему в Дотнете для числовых типов в конвертерных классах решили сделать под пару десятков перегрузок
Ну так уже обсуждали.. Причин достаточно много.
Ну например, мы имеем ограниченное количество типов, которое в обозримое время не будет меняться.
Ну и многие методы и классы в .NET были разработаны до появления обобщений (дженериков). Поддержка перегрузок позволяет сохранить совместимость с существующим кодом и библиотеками.
И не следует сравнивать числовые типы с классами пользователя.
Ну например, мы имеем ограниченное количество типов, которое в обозримое время не будет меняться.
Да что вы говорите! Вот ссылка на нужные и полезные людям числовые структуры (а стандартные числовые типы тоже структуры). Щёлкайте по версиям фреймворка и обнаруживайте, что появились они лишь с третьей-четвёртой версии Дотнет фреймворка (и соответствующих версий языка) и с тех пор всё расширялись. А в первой версии .NET Standard их вообще не было.
И если вам нужно конверить в том числе и эти структуры, то дописывайте расширения в стандартные классы конвертеров или пишите свои конвертеры - т.е. размазывайте логику по работе с этими типами.
Реальный мир он такой - абстракции протекают, задник с нарисованным островом провисает. )))
Вопрос был в размазывании логики типа по проекту.
Странное у вас понимание размазывания.
Использование методов расширения для своего проекта это уже дискуссионный вопрос.
Как и разбрасывание частей одного своего класса по разным местам.
Вообще, Сишарп называется мультипарадигмальным языком. Т.е. в нём есть место
Что об этом говорят:
Это означает, что он поддерживает несколько различных парадигм программирования, что делает его гибким и мощным инструментом для разработчиков. Вот основные парадигмы, которые поддерживает C#:
1. Объектно-ориентированное программирование (ООП): C# изначально был разработан как объектно-ориентированный язык, поддерживающий классы, объекты, наследование, полиморфизм и инкапсуляцию.
2. Процедурное программирование: C# позволяет писать код в процедурном стиле, используя функции и процедуры для структурирования кода.
3. Функциональное программирование: В последних версиях C# были добавлены возможности для функционального программирования, такие как лямбда-выражения, функции высшего порядка и неизменяемые типы данных
1. Обобщенное программирование: C# поддерживает обобщенные типы (дженерики), что позволяет создавать универсальные и повторно используемые компоненты.
2. Событийное программирование: C# активно используется для разработки приложений с графическим интерфейсом пользователя (GUI), где события играют ключевую роль.