Esto provoca una excepción en tiempo de compilación:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
Me doy cuenta de que C # no admite atributos genéricos. Sin embargo, después de mucho buscar en Google, parece que no puedo encontrar la razón.
¿Alguien sabe por qué los tipos genéricos no pueden derivar Attribute
? Alguna teoria?
c#
generics
.net-attributes
Bryan Watts
fuente
fuente
abstract class Base<T>: Attribute {}
que podría usarse para crear clases derivadas genéricas como esta:class Concrete: Base<MyType> {}
[DependsOnProperty<Foo>(f => f.Bar)]
o[ForeignKey<Foo>(f => f.IdBar)]
...Respuestas:
Bueno, no puedo responder por qué no está disponible, pero puedo confirmar que no es un problema de CLI. La especificación CLI no lo menciona (por lo que puedo ver) y si usa IL directamente, puede crear un atributo genérico. La parte de la especificación C # 3 que lo prohíbe: la sección 10.1.4 "Especificación base de clase" no da ninguna justificación.
La especificación de ECMA C # 2 anotada tampoco proporciona información útil, aunque proporciona un ejemplo de lo que no está permitido.
Mi copia de la especificación C # 3 anotada debería llegar mañana ... Veré si eso da más información. De todos modos, definitivamente es una decisión de idioma en lugar de una decisión de tiempo de ejecución.
EDITAR: Respuesta de Eric Lippert (parafraseado): ninguna razón en particular, excepto para evitar la complejidad tanto en el lenguaje como en el compilador para un caso de uso que no agrega mucho valor.
fuente
Un atributo decora una clase en tiempo de compilación, pero una clase genérica no recibe su información de tipo final hasta el tiempo de ejecución. Como el atributo puede afectar la compilación, debe estar "completo" en el momento de la compilación.
Consulte este artículo de MSDN para obtener más información.
fuente
No sé por qué no está permitido, pero esta es una posible solución
fuente
Esto no es realmente genérico y todavía tiene que escribir una clase de atributo específica por tipo, pero puede usar una interfaz base genérica para codificar un poco a la defensiva, escribir un código menor del requerido, obtener beneficios del polimorfismo, etc.
fuente
Esta es una muy buena pregunta. En mi experiencia con atributos, creo que la restricción está en su lugar, porque al reflexionar sobre un atributo que crearía una condición en la que tendría que comprobar si todas las permutaciones posibles de tipo:
typeof(Validates<string>)
,typeof(Validates<SomeCustomType>)
, etc ...En mi opinión, si se requiere una validación personalizada según el tipo, un atributo puede no ser el mejor enfoque.
Quizás una clase de validación que tome a
SomeCustomValidationDelegate
o aISomeCustomValidator
como parámetro sería un mejor enfoque.fuente
Actualmente, esta no es una característica del lenguaje C #, sin embargo, hay mucha discusión sobre el repositorio oficial del lenguaje C # .
De algunas notas de la reunión :
fuente
Mi solución es algo como esto:
fuente