Страницы

Поиск по вопросам

вторник, 15 января 2019 г.

Как в обобщенном классе (generic) задать ограничение “только float или int” для типа?

Есть класс Parameter
public abstract class Parameter { public T Value { get; } //... }
Как в таком классе для типа T задать ограничение только на определенные базовые типы? Хотелось бы иметь что-то наподобие этого:
public abstract class Parameter where T : int, float, double, string { public T Value { get; } //... }
IntelliSense сразу ругается на каждый тип:
"int" не является допустимым ограничением. Тип, использованный в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром-типом.
UPD. Или просто оставить тип без ограничений и ничего страшного в этом нет, что можно случайно создать класс с не таким типом, который ожидалось видеть?
UPD 2. Отвечаю на вопрос для какой цели нужно ограничение типа. Есть некоторая абстракция Параметр, которая инкапсулирует в себе данные определенного базового типа. У него есть поля Значение, Имя и Максимальное и минимальное значение. Читая ответы на вопросы, я понял, что нет смысла ограничивать данный тип параметра.


Ответ

Есть несколько причин, по которым этот код не может работать в C#
where T : int, float, double, string
Когда вы указываете ограничение T : Type то это значит, что T может быть как типа Type так и потомком типа Type. Следовательно, конструкция where T : int, float семантически означает следующее — тип T должен наследовать от типов int и float. Это не сработает по двум причинам:
В C# запрещено множественное наследование Конструкция T : int не может работать, так как int это структура, а структуры не поддерживают наследование. Это свойство классов. Можете проверить это на примере: Generic where T : struct where U : T. (замените struct на class и все заработает)
Зато компилятор предлагает вам рабочие варианты:
Тип, использованный в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром-типом.
Cтруктуры и классы могут имплементировать интерфейсы, поэтому ограничение типа на интерфейс может иметь смысл как для структур, так и для классов, например в ограничение T : IComparable можно подставить как int так и string так как оба этих типа имплементируют этот интерфейс.
Или просто оставить тип без ограничений и ничего страшного в этом нет, что можно случайно создать класс с не таким типом, который ожидалось видеть
Для этого следует ответить на вопрос, для чего вы задаете ограничение типа? Вы видите что-то общее между типами int и string? Вы хотите обращаться к общим членам этих типов или использовать их как-то иначе в полиморфном контексте? Если нет, то, наверное, и нет смысла искусственно ограничивать тип-параметр.

Комментариев нет:

Отправить комментарий