#c# #.net
#c# #.net
Вопрос:
Я хочу сделать что-то вроде этого:
public class MyAttribute : Attribute
{
public Type<BaseAllowedType>[] handledTypes { get; set; }
//...elided...
}
Тогда это позволило бы кому-то добавлять атрибут только к тем типам, которые они обрабатывают, если эти типы наследуются BaseAllowedType
.
Пример:
[MyAttribute(handledTypes = SubType)]
public class MyClass
{
}
public class SubType : BaseAllowedType
{
}
Возможно ли что-то подобное в C #? (Это в Java, но не уверен, что C # позволяет это)
В Java это было бы public Class<? extends BaseAllowedType>[] handledTypes
Комментарии:
1. Вы пробовали ограничения универсального типа ? Может быть, что-то вроде
public class MyClass<T> where T : BaseAllowedType
2. @LewsTherin C # не допускает общих атрибутов, так что это не вариант.
3. @DanielMann Я думаю, это зависит от того, действительно ли OP нуждается в том, чтобы это было атрибутом, или это проблема XY .
4. Я не понимаю, почему это отклонено; это вполне разумный вопрос.
5. Я отмечаю, что вы ссылаетесь конкретно на массивы . К вашему сведению, C # имеет тот же недостаток дизайна, что и Java, в том, что ковариация небезопасного массива является законной. То есть, если у вас есть a
Giraffe[]
, вы можете присвоить егоAnimal[]
переменной, которая затем ужасно вылетит при попытке вставить aTurtle
в массив.
Ответ №1:
Во-первых, это свойство, а не поле.
Во-вторых, свойства не могут быть обобщены в C #, как и атрибуты. (И ни один из них не может быть полями, если на то пошло. Только классы, структуры, интерфейсы, делегаты и методы могут быть обобщены.)
Тем не менее, мы можем ответить на ваш вопрос.
Существует два способа установить ограничение на параметр универсального типа. Первый — наложить ограничение на объявление универсального класса или метода:
class Foo<T> where T : Animal {}
Теперь Foo<Giraffe>
или Foo<Animal>
или Foo<Turtle>
являются законными, но Foo<string>
это не так.
Во-вторых, в интерфейсах и делегатах вы можете поместить аннотацию ковариации:
interface IFoo<out T>
{
T SomeProperty { get; }
}
Но T
должно использоваться только в выходных позициях. С помощью этого ограничения вы можете присвоить IFoo<Giraffe>
переменной типа IFoo<Animal>
, но не наоборот.
Между этими двумя функциями обычно можно создать разумное ограничение типа в C #.
Комментарии:
1. Спасибо за помощь. Я не уверен, что любой из них достигает того, чего я хочу. Я полагаю, что ваше первое означает, что
Foo
это не может быть атрибутом (который мне нужен для основного класса), а ваш второй ожидаетobject
типT
, но мне не нужен объект, мне нужна ссылка на тип (напримерtypeof(MyType)
)2. @DonRhummy: О, если вы хотите, чтобы это были объекты типа runtime, вам не повезло. Средство проверки типов во время компиляции C # не передает информацию о типе среды выполнения , поскольку средство проверки типов во время компиляции выполняется до времени выполнения.
3. @DonRhummy: если вам нужен массив
Type
объектов, в которомType
объекты представляют типы, обладающие определенным свойством, просто проверьте это свойство во время выполнения и выдайте исключение, если задан тип, который не соответствует вашему требованию.4. хорошо, это то, что я сделаю. Я надеялся, что он был встроен в язык, как в Java. Спасибо! Я буду использовать
Contract.Requires<ArgumentException>(...)