Это вызывает исключение во время компиляции:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
Я понимаю, что C # не поддерживает общие атрибуты. Однако, после долгих поисков, я не могу найти причину.
Кто-нибудь знает, почему родовые типы не могут быть получены из Attribute
? Есть теории?
c#
generics
.net-attributes
Брайан Уоттс
источник
источник
abstract class Base<T>: Attribute {}
это может быть использовано для создания общие производные классы, такие как:class Concrete: Base<MyType> {}
[DependsOnProperty<Foo>(f => f.Bar)]
или[ForeignKey<Foo>(f => f.IdBar)]
...Ответы:
Ну, я не могу ответить, почему это не доступно, но я могу подтвердить, что это не проблема CLI. Спецификация CLI не упоминает об этом (насколько я вижу), и если вы используете IL напрямую, вы можете создать общий атрибут. Часть спецификации C # 3, которая запрещает это - раздел 10.1.4 «Базовая спецификация класса» не дает никакого оправдания.
Аннотированная спецификация ECMA C # 2 также не дает никакой полезной информации, хотя она предоставляет пример того, что запрещено.
Моя копия аннотированной спецификации C # 3 должна прибыть завтра ... Я посмотрю, даст ли это больше информации. В любом случае, это определенно решение на языке, а не на этапе исполнения.
РЕДАКТИРОВАТЬ: Ответ от Эрика Липперта (перефразировано): нет особой причины, кроме как избежать сложности как в языке, так и в компиляторе для варианта использования, который не добавляет особой ценности.
источник
Атрибут украшает класс во время компиляции, но универсальный класс не получает свою окончательную информацию о типе до времени выполнения. Поскольку атрибут может влиять на компиляцию, он должен быть «завершен» во время компиляции.
Посмотрите эту статью MSDN для получения дополнительной информации.
источник
Я не знаю, почему это не разрешено, но это одно из возможных решений
источник
Это не является действительно универсальным, и вам все равно придется писать определенный класс атрибутов для каждого типа, но вы можете использовать универсальный базовый интерфейс, чтобы немного защищаться от кода, писать меньше кода, чем требуется, получать преимущества от полиморфизма и т. Д.
источник
Это очень хороший вопрос. По моему опыту , с атрибутами, я думаю , что ограничение на месте , потому что при отражении от атрибута было бы создать условия , в которых вы должны проверить все возможные перестановки типа:
typeof(Validates<string>)
,typeof(Validates<SomeCustomType>)
, и т.д. ...На мой взгляд, если в зависимости от типа требуется пользовательская проверка, атрибут может быть не лучшим подходом.
Возможно, класс валидации, который принимает
SomeCustomValidationDelegate
илиISomeCustomValidator
в качестве параметра, будет лучшим подходом.источник
В настоящее время это не особенность языка C #, однако существует много дискуссий по поводу официального репозитория языка C # .
Из некоторых заметок :
источник
Мой обходной путь примерно такой:
источник