2009-09-12 4 views
20

Si j'ai un ENUM comme celui-ciPourquoi un paramètre Nullable <T> n'est pas un paramètre d'attribut personnalisé valide lorsque T est?

public enum Hungry 
{ 
    Somewhat, 
    Very, 
    CouldEatMySocks 
} 

et un attribut personnalisé comme celui-ci

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

je peux faire

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

mais je ne peux pas le faire

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

Il génère une erreur indiquant que "'NullableHungerLevel' n'est pas un argument d'attribut nommé valide car ce n'est pas un type de paramètre d'attribut valide".

Pourquoi cela n'est-il pas autorisé? Je comprends que fondamentalement ce n'est tout simplement pas sur la liste des types acceptés. Les types valides semblent être des primitives, des énumérations, des chaînes, des types et des tableaux unidimensionnels des types précédents.

Est-ce juste une vieille règle qui n'a pas été mise à jour quand Nullable est arrivé?

+1

Pendant que je suis à l'origine à travers cela dans .NET 3.5 VS2008-il encore ne fonctionne pas dans VS2010 Beta1. –

Répondre

26

Affamé? est égale à NULLABLE <Hungry>, qui, en termes signifie que

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)] 

est égal à

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

Puisque vous ne pouvez utiliser des valeurs constantes dans les arguments d'attributs nommés, vous devrez recourir à la solution de Shimmy.

+0

Maintenant que vous l'expliquez c'est plutôt évident! Merci –

19

Pour contourner ce problème créer un autre initialiseur dans votre Attribut:

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 } 
} 

Je comprends que vous ne comptez pas utiliser les deux propriétés.

+0

La question n'était pas "comment puis-je faire ceci", la question était "pourquoi".Cela ne répond en rien au pourquoi. –

+0

Oui. Ça marche. Je sais comment contourner cela, mais je suis perplexe quant à savoir pourquoi cela ne fonctionne pas comme un paramètre nommé. Cela semble incohérent pour moi. –

+0

Dois-je supprimer cette réponse? Malheureusement, je n'ai pas de réponses sur la partie pourquoi: ( – Shimmy

5

Les attributs peuvent avoir comme seuls paramètres des primitives, des expressions de typeof et une expression de création de tableau.

Nullable est une structure.

Par conséquent, il n'est pas autorisé là.

Je soupçonne que le format de fichier d'assemblage lui-même ne permet pas le stockage de types complexes comme des structures à l'endroit où les valeurs d'attributs sont stockées.

Je ne connais aucun plan pour changer cela. Mais je ne peux pas expliquer pourquoi cette restriction existe.

1

Au lieu de créer une énumération nullable, vous pouvez créer une valeur par défaut pour cette énumération. Enum défaut de choix de 1ère valeur, donc définissez votre ENUM comme celui-ci

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

dans votre code, vous pouvez le faire pour vérifier null

if(default(Hungry) == HungerLevel)//no value has been set 
Questions connexes