#c_sharp #net #generics
Есть класс 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. Отвечаю на вопрос для какой цели нужно ограничение типа. Есть некоторая абстракция Параметр, которая инкапсулирует в себе данные определенного базового типа. У него есть поля Значение, Имя и Максимальное и минимальное значение. Читая ответы на вопросы, я понял, что нет смысла ограничивать данный тип параметра.
Ответы
Ответ 1
Есть несколько причин, по которым этот код не может работать в C# where T : int, float, double, string Когда вы указываете ограничение T : Type то это значит, что T может быть как типа Type так и потомком типа Type. Следовательно, конструкция where T : int, float семантически означает следующее — тип T должен наследовать от типов int и float. Это не сработает по двум причинам: В C# запрещено множественное наследование Конструкция T : int не может работать, так как int это структура, а структуры не поддерживают наследование. Это свойство классов. Можете проверить это на примере: Genericwhere T : struct where U : T. (замените struct на class и все заработает) Зато компилятор предлагает вам рабочие варианты: Тип, использованный в качестве ограничения, должен быть интерфейсом, незапечатанным классом или параметром-типом. Cтруктуры и классы могут имплементировать интерфейсы, поэтому ограничение типа на интерфейс может иметь смысл как для структур, так и для классов, например в ограничение T : IComparable можно подставить как int так и string так как оба этих типа имплементируют этот интерфейс. Или просто оставить тип без ограничений и ничего страшного в этом нет, что можно случайно создать класс с не таким типом, который ожидалось видеть Для этого следует ответить на вопрос, для чего вы задаете ограничение типа? Вы видите что-то общее между типами int и string? Вы хотите обращаться к общим членам этих типов или использовать их как-то иначе в полиморфном контексте? Если нет, то, наверное, и нет смысла искусственно ограничивать тип-параметр. Ответ 2
К сожалению, никак. Можно использовать только constraints указанные в документации: https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters В качестве обходного пути можно создать класс-обёртку для нужных типов: public class WrappedInt { public int Value { get; } public WrappedInt(int value) { this.Value = value; } } public class Foowhere T : WrappedInt, WrappedFloat, ... { public Foo(T ariphmeticValue) { } } UPD. Касаемо последнего вопроса: сильно зависит от задачи. Если использование других типов будут вызывать unhandled exceptions - это плохо.
Комментариев нет:
Отправить комментарий