446 votos

¿Por qué C # no lo quiera tipos de atributos genéricos?

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 C # no admite atributos genéricos. Sin embargo, después de mucho buscar en Google, me parece que no puede encontrar la razón.

¿Alguien sabe por qué los tipos genéricos no pueden fundar en Attribute ? ¿Alguna teoría?

310voto

Jon Skeet Puntos 692016

Bueno, yo no puedo responder por qué no está disponible, pero me puede confirmar que no es un CLI problema. El CLI de especificaciones no lo menciona (por lo que puedo ver) y si utiliza IL directamente, puede crear un atributo genérico. La parte de la C# 3 especificación de que la prohíbe sección 10.1.4 "de la Clase base de la especificación de" no dar ningún tipo de justificación.

Anotado ECMA C# 2 spec no da ninguna información útil, aunque no proporciona un ejemplo de lo que no está permitido.

Mi copia de la annotated C# 3 spec debería de llegar mañana... voy a ver si eso le da más información. De todos modos, es definitivamente un lenguaje de decisión en lugar de en tiempo de ejecución.

EDIT: Respuesta de Eric Lippert (parafraseado): sin ninguna razón en particular, excepto a evitar la complejidad en el lenguaje y compilador para un caso de uso que no agrega mucho valor.

69voto

GalacticCowboy Puntos 8185

Un atributo decora una clase en tiempo de compilación, pero una clase genérica no recibe su información de tipo definitivo hasta que el tiempo de ejecución. Dado que el atributo puede afectar a la compilación, que tiene que ser "completa" en tiempo de compilación.

Consulte este artículo de MSDN para obtener más información.

15voto

GeekyMonkey Puntos 5036

No sé por qué no está permitido, pero esto es una posible solución

 [AttributeUsage(AttributeTargets.Class)]
public class ClassDescriptionAttribute : Attribute
{
    public ClassDescriptionAttribute(Type KeyDataType)
    {
        _KeyDataType = KeyDataType;
    }

    public Type KeyDataType
    {
        get { return _KeyDataType; }
    }
    private Type _KeyDataType;
}


[ClassDescriptionAttribute(typeof(string))]
class Program
{
    ....
}
 

10voto

nawfal Puntos 13500

Esto no es realmente genérico y usted todavía tiene que escribir la clase atributo específico según el tipo, pero puede ser capaz de utilizar una interfaz de base genérica para codificar un poco a la defensiva, escribir menos código que requiere de otro modo, obtener beneficios del polimorfismo etc

 //an interface which means it can't have its own implementation. 
//You might need to use extension methods on this interface for that.
public interface ValidatesAttribute<T>
{
    T Value { get; } //or whatever that is
    bool IsValid { get; } //etc
}

public class ValidatesStringAttribute : Attribute, ValidatesAttribute<string>
{
    //...
}
public class ValidatesIntAttribute : Attribute, ValidatesAttribute<int>
{
    //...
}

[ValidatesString]
public static class StringValidation
{

}
[ValidatesInt]
public static class IntValidation
{

}
 

8voto

ichiban Puntos 4568

Esta es una muy buena pregunta. En mi experiencia con los atributos, creo que la restricción está en el lugar porque a la hora de reflexionar sobre un atributo que crearía una condición en la cual usted tendrá que comprobar para todo tipo de permutaciones: typeof(Validates<string>), typeof(Validates<SomeCustomType>), etc...

En mi opinión, si una validación personalizada es necesario según el tipo de un atributo no puede ser el mejor enfoque.

Tal vez una validación de la clase que lleva en un SomeCustomValidationDelegate o ISomeCustomValidator como parámetro sería un mejor enfoque.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: