Comment donner à une propriété C# Auto une valeur par défaut?

comment attribuer une valeur par défaut à une propriété C# Auto? J'utilise soit le constructeur, soit l'ancienne syntaxe.

utilisant le constructeur:

class Person 
{
    public Person()
    {
        Name = "Default Name";
    }
    public string Name { get; set; }
}

utilisant la syntaxe de propriété normale (avec une valeur par défaut)

private string name = "Default Name";
public string Name 
{
    get 
    {
        return name;
    }
    set
    {
        name = value;
    }
}

y a-t-il un meilleur moyen?

1474
demandé sur Palantir 2008-09-03 01:29:41

21 réponses

En C# 5 et versions antérieures, pour donner automatique de la mise en œuvre des propriétés d'une valeur par défaut, vous devez le faire dans un constructeur.

la capacité d'avoir des initialisateurs de propriétés automatiques est incluse depuis C# 6.0. La syntaxe est:

public int X { get; set; } = x; // C# 6 or higher
1658
répondu Darren Kopp 2015-10-23 06:59:26

Modifier 1/2/15

avec C# 6 Vous pouvez initialiser les auto-propriétés directement (enfin!), il y a maintenant d'autres réponses dans le fil qui les décrivent.

pour C# 5 et inférieur:

Si l'utilisation prévue de l'attribut n'est pas réellement définir les valeurs des propriétés, vous pouvez utiliser la réflexion pour définir toujours de toute façon...

public class DefaultValuesTest
{    
    public DefaultValuesTest()
    {               
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
        {
            DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];

            if (myAttribute != null)
            {
                property.SetValue(this, myAttribute.Value);
            }
        }
    }

    public void DoTest()
    {
        var db = DefaultValueBool;
        var ds = DefaultValueString;
        var di = DefaultValueInt;
    }


    [System.ComponentModel.DefaultValue(true)]
    public bool DefaultValueBool { get; set; }

    [System.ComponentModel.DefaultValue("Good")]
    public string DefaultValueString { get; set; }

    [System.ComponentModel.DefaultValue(27)]
    public int DefaultValueInt { get; set; }
}
245
répondu Chuck Rostance 2015-01-12 15:58:24

quand vous insérez une valeur initiale pour une variable, cela sera fait implicitement dans le constructeur de toute façon.

je dirais que cette syntaxe est la meilleure pratique en C# jusqu'à 5:

class Person 
{
    public Person()
    {
        //do anything before variable assignment

        //assign initial values
        Name = "Default Name";

        //do anything after variable assignment
    }
    public string Name { get; set; }
}

comme cela vous donne le contrôle clair des valeurs d'ordre sont attribuées.

à partir de C#6 Il y a une nouvelle voie:

public string Name { get; set; } = "Default Name"
131
répondu Keith 2015-09-08 16:23:20

DefaultValueAttribute ne fonctionne que dans le vs designer. Il n'initialisera pas la propriété à cette valeur.

Voir DefaultValue attribut ne fonctionne pas avec mon Auto Propriété

74
répondu Darren Kopp 2017-05-23 11:55:02

parfois j'utilise ceci, si Je ne veux pas qu'il soit réellement mis et persisté dans mon db:

class Person
{
    private string _name; 
    public string Name 
    { 
        get 
        {
            return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
        } 

        set { _name = value; } 
    }
}

évidemment si ce n'est pas une chaîne de caractères, alors je pourrais rendre l'objet nul ( double?, int? ) et vérifier si elle est null, le retour d'un défaut, ou le retour de la valeur de sa valeur.

alors je peux faire une vérification dans mon dépôt pour voir si c'est mon défaut et ne pas persister, ou faire une vérification de backdoor pour voir l'état vrai de la valeur de soutien, avant économie.

Espère que ça aide!

49
répondu crucible 2008-09-02 23:07:27

à partir de C# 6.0 , nous pouvons attribuer une valeur par défaut aux propriétés auto-implémentées.

public string Name { get; set; } = "Some Name";

nous pouvons aussi créer une propriété auto implémentée en lecture seule comme:

public string Name { get; } = "Some Name";

Voir: C# 6: les Premières réactions , les Initialiseurs de propriétés implémentées automatiquement Par Jon Skeet

26
répondu Habib 2015-07-24 17:22:22

En C# 6.0 c'est un jeu d'enfant!

vous pouvez le faire dans la déclaration Class elle-même, dans les déclarations de propriété.

public class Coordinate
{ 
    public int X { get; set; } = 34; // get or set auto-property with initializer

    public int Y { get; } = 89;      // read-only auto-property with initializer

    public int Z { get; }            // read-only auto-property with no initializer
                                     // so it has to be initialized from constructor    

    public Coordinate()              // .ctor()
    {
        Z = 42;
    }
}
18
répondu Shiva 2017-09-29 16:34:33

dans la Version de C# (6.0) et plus , vous pouvez faire:

Pour les propriétés Readonly

public int ReadOnlyProp => 2;

pour les biens inscriptibles et déchiffrables

public string PropTest { get; set; } = "test";

dans la version actuelle de C# (7.0) , vous pouvez faire: (le snippet plutôt affiche comment vous pouvez utiliser l'expression corsé obtenir / définir des accesseurs pour faire est plus compact quand avec l'aide de champs de sauvegarde)

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }
12
répondu ANewGuyInTown 2017-09-26 05:39:46

petit échantillon complet:

using System.ComponentModel;

private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
    get { return bShowGroup; }
    set { bShowGroup = value; }
}
11
répondu ghiboz 2016-11-21 11:14:17

ma solution est d'utiliser un attribut personnalisé qui fournit la valeur par défaut initialisation de la propriété par constante ou en utilisant le type de propriété initializer.

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InstanceAttribute : Attribute
{
    public bool IsConstructorCall { get; private set; }
    public object[] Values { get; private set; }
    public InstanceAttribute() : this(true) { }
    public InstanceAttribute(object value) : this(false, value) { }
    public InstanceAttribute(bool isConstructorCall, params object[] values)
    {
        IsConstructorCall = isConstructorCall;
        Values = values ?? new object[0];
    }
}

Pour utiliser cet attribut, il est nécessaire d'hériter d'une classe de base classe de l'initialiseur ou l'utilisation d'une assistance statique méthode:

public abstract class DefaultValueInitializer
{
    protected DefaultValueInitializer()
    {
        InitializeDefaultValues(this);
    }

    public static void InitializeDefaultValues(object obj)
    {
        var props = from prop in obj.GetType().GetProperties()
                    let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
                    where attrs.Any()
                    select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
        foreach (var pair in props)
        {
            object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
                            ? pair.Attr.Values[0]
                            : Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
            pair.Property.SetValue(obj, value, null);
        }
    }
}

exemple d'utilisation:

public class Simple : DefaultValueInitializer
{
    [Instance("StringValue")]
    public string StringValue { get; set; }
    [Instance]
    public List<string> Items { get; set; }
    [Instance(true, 3,4)]
    public Point Point { get; set; }
}

public static void Main(string[] args)
{
    var obj = new Simple
        {
            Items = {"Item1"}
        };
    Console.WriteLine(obj.Items[0]);
    Console.WriteLine(obj.Point);
    Console.WriteLine(obj.StringValue);
}

sortie:

Item1
(X=3,Y=4)
StringValue
9
répondu introspected 2013-01-18 07:52:54

en plus de la réponse déjà acceptée, pour le scénario où vous voulez définir une propriété par défaut comme une fonction d'autres propriétés, Vous pouvez utiliser notation du corps d'expression sur C#6.0 (et plus) pour des constructions encore plus élégantes et concises comme:

public class Person{

    public string FullName  => $"{First} {Last}"; // expression body notation

    public string First { get; set; } = "First";
    public string Last { get; set; } = "Last";
}

vous pouvez utiliser ce qui précède de la façon suivante

    var p = new Person();

    p.FullName; // First Last

    p.First = "Jon";
    p.Last = "Snow";

    p.FullName; // Jon Snow

pour pouvoir utiliser la notation ci-dessus"=>", la propriété doit être lue seulement, et vous n'utilisez pas le mot-clé get accessor.

détails sur MSDN

8
répondu brakeroo 2016-10-30 02:16:41

en C# 6 et au-dessus vous pouvez simplement utiliser la syntaxe:

public object Foo { get; set; } = bar;

notez que pour avoir une propriété readonly omettez simplement l'ensemble, comme suit:

public object Foo { get; } = bar;

vous pouvez également assigner readonly auto-propriétés du constructeur.

auparavant, j'ai répondu comme suit.

j'éviterais d'ajouter un défaut au constructeur; laisser cela pour les assignations dynamiques et éviter d'avoir deux points où la variable est assignée (i.e. le type default et dans le constructeur). En général, j'écrirais simplement une propriété normale dans de tels cas.

une autre option est de faire ce que ASP.Net does and define defaults via un attribut:

http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

6
répondu Lex 2017-06-17 15:43:26

dans le constructeur. Le but du constructeur est d'initialiser ses membres de données.

4
répondu RayLoveless 2016-07-18 16:39:49

avez-vous essayé d'utiliser les méthodes DefaultValueAttribute ou ShouldSerialize et Reset en conjonction avec le constructeur? Je pense que l'une de ces deux méthodes est nécessaire si vous faites une classe qui pourrait apparaître sur la surface du concepteur ou dans une grille de propriété.

2
répondu OwenP 2008-09-02 21:38:10
public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}
2
répondu FloodMoo 2014-09-04 20:44:06

Personnellement, je ne vois pas l'intérêt d'en faire une propriété, si vous n'allez pas faire quoi que ce soit au-delà de l'auto-propriété. Il suffit de laisser un champ. L'avantage d'encapsulation pour ces articles sont juste des harengs rouges, parce qu'il n'y a rien derrière eux pour encapsuler. Si vous avez besoin de changer l'implémentation sous-jacente, vous êtes toujours libre de les reformater en propriétés sans casser aucun code dépendant.

Hmm... peut-être que ce sera le sujet de sa propre question plus tard

1
répondu Joel Coehoorn 2008-09-03 03:43:20

pour clarifier, oui, vous devez définir des valeurs par défaut dans le constructeur pour les objets dérivés de la classe. Vous devrez assurer le constructeur existe avec le bon modificateur d'accès pour la construction. Si l'objet n'est pas instancié, par exemple s'il n'a pas de constructeur (par exemple méthodes statiques), alors la valeur par défaut peut être définie par le champ. Le raisonnement ici est que l'objet lui-même sera créé qu'une seule fois et vous n'avez pas l'instancier.

@Darren Kopp - bonne réponse, propre et correcte. Et pour le répéter, vous pouvez écrire des constructeurs pour des méthodes abstraites. Vous avez juste besoin d'y accéder depuis la classe de base lorsque vous écrivez le constructeur:

constructeur à la classe de Base:

public BaseClassAbstract()
{
    this.PropertyName = "Default Name";
}

Constructeur à la Dérivée de / en Béton / Sous-Catégorie:

public SubClass() : base() { }

le point ici est que la variable d'instance tirée de la classe de base peut enterrer votre nom de champ de base. Réglage de l'actuel objet instancié de la valeur à l'aide de "ce."vous permettra de former correctement votre objet par rapport à l'instance courante et aux niveaux de permission requis (modificateurs d'accès) où vous l'instanciez.

1
répondu Zack Jannsen 2013-06-07 14:26:41

utiliser le constructeur parce que"lorsque le constructeur est terminé, la Construction doit être terminée". les propriétés sont comme les états que vos classes contiennent, si vous deviez initialiser un état par défaut, vous le feriez dans votre constructeur.

1
répondu Preet Singh 2016-01-11 11:33:09
class Person 
{    
    /// Gets/sets a value indicating whether auto 
    /// save of review layer is enabled or not
    [System.ComponentModel.DefaultValue(true)] 
    public bool AutoSaveReviewLayer { get; set; }
}
0
répondu Nag 2014-07-31 13:55:16

je pense que ça ferait l'affaire si tu donnais à Quelqu'un un retard de false.

private bool _SomeFlagSet = false;
public bool SomeFlag
{
    get
    {
        if (!_SomeFlagSet)
            SomeFlag = false;        

        return SomeFlag;
    }
    set
    {
        if (!_SomeFlagSet)
            _SomeFlagSet = true;

        SomeFlag = value;        
    }
}
-2
répondu user3076134 2013-12-06 21:50:59

initialise en ligne, utiliser les constructeurs pour initialiser est une mauvaise pratique et entraînera plus de changements de rupture plus tard.

-3
répondu dbobrowski 2012-09-13 19:13:27