Os atributos têm sido parte do .NET desde o início. Como tal, eles foram criados antes dos genéricos serem introduzidos (e nunca serem capturados), o que significa que, para se referir a um tipo no atributo, é necessário expor um parâmetro ou uma propriedade Type. Por exemplo,
[TypeConverter(typeof(X))]
Existem algumas limitações para esse padrão. No exemplo acima, X deve ter um construtor sem parâmetros e herdar de TypeConverter. Isso não pode ser imposto pelo compilador, portanto, o desenvolvedor não será alertado sobre erros até o tempo de execução.
Se, em vez disso, usarmos um parâmetro de tipo genérico, as restrições podem ser aplicadas reforçando a regra em tempo de compilação. E a sintaxe será um pouco mais limpa.
[TypeConverter<X>]
Em teoria, a proposta para permitir atributos genéricos é uma mudança muito simples. O CLR já suporta o conceito; é apenas uma questão de expô-lo nas linguagens .NET. Porém teoria e prática muitas vezes não combinam e só porque o CLR supostamente suporta isso, não significa necessariamente que o faça. Jan Kotas explica:
Acho que a natureza desse problema é semelhante as ref locals e returns. Os ref locals e returns não são chaveados por nenhuma API. Devem funcionar bem com o tempo de execução, ferramentas e bibliotecas existentes na teoria. Na prática, não funcionam muito bem porque expõem bugs e limitações preexistentes porque os caminhos que os manipulam nunca foram exercitados ou não eram explicitamente esperados. Os bugs e problemas relacionados a retornos de referência estão apenas começando a aparecer, pois as pessoas estão começando a usar o recurso e a encontrar locais onde o mesmo não funciona. Eu acho que isso é bom e esperado. Deveríamos reconhecê-lo, e não reagir a ele, retrocedendo o recurso como fizemos para os construtores de valuetype padrão há algum tempo atrás.
Esse recurso é bem parecido. Não há nada no ECMA que proíba os atributos genéricos, e eles devem funcionar muito bem na teoria. Na prática, eles não funcionam. Várias partes do sistema precisam ser atualizadas para que funcionem bem:
- Há mais do que um runtime para se preocupar como você disse (Mono, CoreRT, framework completo);
- Algumas das ferramentas que operam em IL provavelmente também serão afetadas (compiladores, ferramentas baseadas em Cecil ou baseadas em CCI2);
- Novas APIs para acessar os atributos genéricos talvez sejam necessárias (por exemplo, as APIs de reflexão existentes não permitem que você acesse os atributos genéricos com eficiência - você deve sempre enumerar).
Uma limitação desta proposta é que os atributos devem ser "fechados" em tempo de compilação. Para ilustrar o que isso significa, aqui está um exemplo de um atributo genérico aberto da proposta.
[SomeAttribute<T>]
public void DoSomething<T>(T input) { }
Como T não é definido em tempo de compilação, a reflexão não saberá o que retornar para essa expressão.
typeof(GenericClass<>).GetMethod("DoSomething").GetCustomAttributes()
Status
Atualmente, o recurso atributos genéricos é listado no roadmap C# 8 com o status "Em andamento".