web-dev-qa-db-fra.com

Attribut .NET DefaultValue

J'ai entendu des gens dire différentes choses sur l'attribut DefaultValue, notamment:

  • "Il définit la valeur de la propriété avant que quiconque ne l'utilise."
  • "Cela ne fonctionne pas pour les propriétés automatiques."
  • "Ce n'est que pour la décoration. Vous devez définir manuellement les valeurs par défaut actuelles."

Lequel (le cas échéant) a raison? Est-ce que DefaultValue définit réellement les valeurs par défaut? Y a-t-il des cas où cela ne fonctionne pas? Est-il préférable de ne pas l'utiliser?

45
Aaron

L'endroit où j'ai généralement utilisé DefaultValue est destiné aux classes sérialisées/désérialisées au format XML. Il ne définit pas la valeur par défaut lors de l'instanciation et n'a pas d'incidence sur les propriétés automatiques.

De MSDN:

Un DefaultValueAttribute ne provoque pas l'initialisation automatique d'un membre avec la valeur de l'attribut. Vous devez définir la valeur initiale dans votre code.

MSDN - DefaultValueAttribute Class


Edit: Comme Roland le fait remarquer, et comme d’autres le mentionnent dans leurs réponses, cet attribut est également utilisé par le concepteur de formulaires.

47
STW

Comme tous les attributs, il s’agit de métadonnées, et à ce titre "C’est uniquement pour la décoration. Vous devez définir manuellement les valeurs par défaut réelles." est le plus proche.

MSDN poursuit à propos de DefaultValueAttribute :

Un DefaultValueAttribute ne provoque pas l'initialisation automatique d'un membre avec la valeur de l'attribut. Vous devez définir la valeur initiale dans votre code.

c.-à-d. que vous devez toujours faire correspondre le constructeur à ce que vous dites est la valeur par défaut pour que le code qui l’approuve fonctionne toujours, tel que la sérialisation XML intégrée les utilisera pour déterminer si la propriété doit être sérialisée ou non; De même, le concepteur de formulaire utilisera la variable DefaultValues pour déterminer le code à générer automatiquement.

12
Rowland Shaw

Pour mettre à jour cela quatre ans plus tard: Actuellement, la configuration du paramètre DefaultValueHandling de JSON.net permet à DefaultValue de fonctionner comme prévu par @aaron:

[JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[DefaultValue(true)]
public bool AllowUploading { get; set; }
11
John Hatton

En fait, vous pouvez le "forcer" à travailler sur n'importe quelle classe assez facilement.

Vous devez d’abord écrire une méthode d’extension d’objet dans l’espace de noms système:

public static class ObjectExtensions
{
    public static void InitializePropertyDefaultValues(this object obj)
    {
        PropertyInfo[] props = obj.GetType().GetProperties();
        foreach (PropertyInfo prop in props)
        {
            var d = prop.GetCustomAttribute<DefaultValueAttribute>();
            if (d != null)
                prop.SetValue(obj, d.Value);
        }
    }
}

Ensuite, dans le constructeur d'une classe suffisamment élevée dans la hiérarchie de vos classes nécessitant une telle initialisation automatique, il vous suffit d'ajouter une ligne:

    public MotherOfMyClasses()
    {
        this.InitializePropertyDefaultValues();
    }
8
Thastograth

"Il définit la valeur de la propriété avant toute autre utilisation." --> Non, la valeur par défaut s’applique uniquement au concepteur. une valeur par défaut ne sera pas sérialisée dans le code du concepteur.

"Cela ne fonctionne pas pour les propriétés automatiques." --> Non

"C'est uniquement pour la décoration. Vous devez définir manuellement les valeurs par défaut actuelles." --> Non. En raison de la sérialisation de Designer. Mais vous devez le définir manuellement.

2
gsharp

Dans les dernières versions de C#, vous pouvez faire:

public class InitParam
{
    public const int MyInt_Default = 32;
    public const bool MyBool_Default = true;

    [DefaultValue(MyInt_Default)]
    public int MyInt{ get; set; } = MyInt_Default;

    [DefaultValue(MyBool_Default)]
    public bool MyBool{ get; set; } = MyBool_Default;
}
1
Andrei Krasutski

De MSDN help:

AttributeCollection^ attributes = TypeDescriptor::GetProperties( this )[ "MyProperty" ]->Attributes;

/* Prints the default value by retrieving the DefaultValueAttribute 
      * from the AttributeCollection. */
DefaultValueAttribute^ myAttribute = dynamic_cast<DefaultValueAttribute^>(attributes[ DefaultValueAttribute::typeid ]);
Console::WriteLine( "The default value is: {0}", myAttribute->Value );

Je dois définir l'attribut de valeur par défaut sur quelque chose de non statique. Comment puis-je fondamentalement le définir quand je veux?


Résolu en surchargeant les fonctions ShouldSerialize dans la classe contenant les propriétés. 

Exemple:

property System::String^ Z {
            System::String^ get(){...}
            void set(System::String^ value) {...}
        }

        bool ShouldSerializeZ() {
            return Z != <call to run time objects>
        }
1
Adam

vous pouvez faire en sorte que ce type de magie se produise avec des cadres orientés aspect comme Afterthought ou Postsharp.

0
Thomas Haller