2009-09-12 21 views
20

Si tengo una enumeración como esto¿Por qué un Nullable <T> no es un parámetro de atributo personalizado válido cuando T es?

public enum Hungry 
{ 
    Somewhat, 
    Very, 
    CouldEatMySocks 
} 

y un atributo personalizado como éste

public class HungerAttribute : Attribute 
{ 
    public Hungry HungerLevel { get; set; } 
    public Hungry? NullableHungerLevel { get; set; } 
} 

que pueda hacer esto

[Hunger(HungerLevel = Hungry.CouldEatMySocks)] 
public class Thing1 

pero no puedo hacer esto

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)] 
public class Thing2 

Genera un error que dice "'NullableHungerLevel' no es un argumento de atributo con nombre válido porque no es un tipo de parámetro de atributo válido".

¿Por qué no está permitido? Entiendo que, fundamentalmente, simplemente no está en la lista de tipos aceptados. Los tipos válidos parecen ser primitivas, enumeraciones, cadenas, tipos y matrices unidimensionales de los tipos anteriores.

¿Es esta una regla antigua que no se actualizó cuando apareció Nullable?

+1

Mientras que originalmente encontré con esto en .NET 3.5 VS2008 todavía no funciona en VS2010 Beta1. –

Respuesta

26

Hambre? es igual a nullable <Hungry>, que en términos quiere decir que

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)] 

es igual a

[Hunger(NullableHungerLevel = new Nullable<Hungry>(Hungry.CouldEatMySocks))] 

Dado que sólo puede utilizar valores constantes en los argumentos de los atributos mencionados, tendrá que recurrir a la solución de la vibración excesiva.

+0

Ahora que lo explicas es algo obvio! Gracias –

19

Para evitar esto crear otro inicializador en su Atributo:

class Program 
{ 
    [Hunger()] 
    static void Main(string[] args) 
    { 
    } 

    public sealed class HungerAttribute : Attribute 
    { 
    private readonly Hungry? _HungerLevel; 
    public Hungry? HungerLevel { get { return _HungerLevel; } } 

    public bool IsNull { get { return !_HungerLevel.HasValue; } }   

    public HungerAttribute() 
    { 
    } 

    //Or: 
    public HungerAttribute(Hungry level) 
    { 
     _HungerLevel = level; 
    } 
    } 

    public enum Hungry { Somewhat, Very, CouldEatMySocks } 
} 

entiendo que usted no va a utilizar ambas propiedades.

+0

La pregunta no era "¿cómo hago esto?", La pregunta era "por qué".Esto de ninguna manera responde el por qué. –

+0

Sí. Eso funciona. Sé cómo evitarlo, pero estoy desconcertado de por qué no funciona como un parámetro nombrado. Me parece inconsistente. –

+0

¿Debo eliminar esta respuesta? Desgraciadamente, no tengo respuestas sobre la parte del por qué :( – Shimmy

5

Los atributos pueden tener como únicos parámetros primitivas, expresiones typeof y expresión de creación de matriz.

Nullable es una estructura.

Por lo tanto, no está permitido allí.

Sospecho que el formato del archivo de ensamblaje en sí no permite el almacenamiento de tipos complejos como estructuras en el lugar donde se almacenan los valores de los atributos.

No tengo ningún plan para cambiar eso. Pero no puedo explicar por qué existe esta restricción.

1

En lugar de crear una enumeración nullable, puede crear el valor predeterminado para esa enumeración. predeterminado enumeración de recogida desde el 1 de valor, por lo que su enumeración establece como esto

public enum Hungry 
{ 
    None, 
    Somewhat, 
    Very, 
    CouldEatMySocks 
} 

en su código que podría hacer esto para comprobar si hay nula

if(default(Hungry) == HungerLevel)//no value has been set 
Cuestiones relacionadas