Isso causa uma exceção em tempo de compilação:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
Sei que o C # não suporta atributos genéricos. No entanto, depois de muito pesquisar no Google, parece que não consigo encontrar o motivo.
Alguém sabe por que os tipos genéricos não podem derivar Attribute
? Alguma teoria?
c#
generics
.net-attributes
Bryan Watts
fonte
fonte
abstract class Base<T>: Attribute {}
que poderia ser usada para criar classes derivadas genéricas como esta:class Concrete: Base<MyType> {}
[DependsOnProperty<Foo>(f => f.Bar)]
ou[ForeignKey<Foo>(f => f.IdBar)]
...Respostas:
Bem, não sei responder por que não está disponível, mas posso confirmar que não é um problema de CLI. A especificação da CLI não a menciona (até onde posso ver) e, se você usar o IL diretamente, poderá criar um atributo genérico. A parte da especificação do C # 3 que a proíbe - seção 10.1.4 "Especificação básica da classe" não fornece nenhuma justificativa.
A especificação ECMA C # 2 anotada também não fornece informações úteis, embora forneça um exemplo do que não é permitido.
Minha cópia da especificação C # 3 anotada deve chegar amanhã ... Vou ver se isso fornece mais informações. Enfim, é definitivamente uma decisão de idioma, e não de execução.
EDIT: Resposta de Eric Lippert (parafraseado): nenhum motivo específico, exceto para evitar complexidade no idioma e no compilador para um caso de uso que não agrega muito valor.
fonte
Um atributo decora uma classe no tempo de compilação, mas uma classe genérica não recebe suas informações de tipo final até o tempo de execução. Como o atributo pode afetar a compilação, ele deve estar "completo" no momento da compilação.
Consulte este artigo do MSDN para obter mais informações.
fonte
Não sei por que não é permitido, mas esta é uma solução possível
fonte
Isso não é verdadeiramente genérico e você ainda precisa escrever uma classe de atributo específica por tipo, mas pode usar uma interface básica genérica para codificar um pouco defensivamente, escrever um código menor do que o necessário, obter benefícios do polimorfismo etc.
fonte
Esta é uma pergunta muito boa. Na minha experiência com atributos, acho que a restrição está em vigor porque ao refletir sobre um atributo que iria criar uma condição em que você teria que verificar todas as permutações de tipos possíveis:
typeof(Validates<string>)
,typeof(Validates<SomeCustomType>)
, etc ...Na minha opinião, se uma validação personalizada for necessária, dependendo do tipo, um atributo pode não ser a melhor abordagem.
Talvez uma classe de validação que aceite um
SomeCustomValidationDelegate
ou umISomeCustomValidator
como parâmetro seja uma abordagem melhor.fonte
No momento, esse não é um recurso do idioma C #, mas há muita discussão sobre o repositório oficial do idioma C # .
De algumas notas da reunião :
fonte
Minha solução alternativa é algo como isto:
fonte