objet - visual c# class constructor




Comment attribuer une valeur par défaut à une propriété Auto C#? (15)

Comment attribuer une valeur par défaut à une propriété Auto C #? J'utilise le constructeur ou je reviens à l'ancienne syntaxe.

Utilisation du constructeur:

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

Utilisation de 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?


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

Vous pouvez le faire dans la déclaration de Class elle-même, dans les déclarations de déclaration 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;
    }
}



En C # 5 et plus tôt, pour donner aux propriétés implémentées automatiquement une valeur par défaut, vous devez le faire dans un constructeur.

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

public int X { get; set; } = x; // C# 6 or higher

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 en fonction d'autres propriétés, vous pouvez utiliser la notation de 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 manière 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 en lecture seule et vous n'utilisez pas le mot clé get accessor.

Détails sur MSDN


En version de C # (6.0) et plus , vous pouvez faire:

Pour les propriétés Readonly

public int ReadOnlyProp => 2;

Pour les propriétés à la fois lisibles et lisibles

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

Dans la version actuelle de C # (7.0) , vous pouvez faire: (L'extrait montre plutôt comment vous pouvez utiliser des accesseurs get / set d'expression de corps à rendre plus compact lorsque vous utilisez des champs de backing)

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }

Lorsque vous insérez une valeur initiale pour une variable, elle sera implicitement exécutée dans le constructeur.

Je dirais que cette syntaxe était 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 un contrôle clair de l'ordre des valeurs sont affectées.

À partir de C # 6, il y a une nouvelle façon:

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

Ma solution consiste à utiliser un attribut personnalisé qui fournit une initialisation de propriété de valeur par défaut par une constante ou en utilisant un initialiseur de type de propriété.

[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 à partir d'un initialiseur de classe de base spécial ou d'utiliser une méthode d'aide statique:

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

Parfois je l'utilise, si je ne veux pas que ce soit réellement défini et persiste 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, je peux rendre l'objet Nullable (double ?, int?) Et vérifier si elle est nulle, retourner une valeur par défaut, ou retourner la valeur à laquelle elle est définie.

Ensuite, 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 backdoor pour voir le vrai statut de la valeur de sauvegarde, avant de sauvegarder.

J'espère que cela pourra aider!


Personnellement, je ne vois pas l'intérêt d'en faire une propriété si vous ne faites rien du tout au-delà de l'auto-propriété. Laissez-le comme un champ. Les avantages de l'encapsulation pour ces objets ne sont que des harengs rouges, car il n'y a rien derrière eux à encapsuler. Si vous avez besoin de modifier l'implémentation sous-jacente, vous pouvez toujours les refactoriser en tant que propriétés sans casser le code dépendant.

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


Tapez Prop et appuyez sur le bouton "TAB" et Visual Studio vous suggérons le code suivant,

public int MyProperty { get; set; }

après que vous pouvez changer le modificateur, le type de données, le nom et facilement assigner l'ensemble et obtenir des valeurs.

si vous avez besoin d'utiliser une variable dans une autre classe, vous pouvez l'utiliser comme suit

public static int MyProperty { get; set; }

dans le code, vous pouvez attribuer une variable

MyProperty=1;

dans une autre classe, vous pouvez l' utiliser ,

MessageBox.Show(Classname.MyProperty);

Utilisez le constructeur car "Lorsque le constructeur est fini, la construction devrait être terminée". les propriétés sont comme les états de vos classes, si vous deviez initialiser un état par défaut, vous le feriez dans votre constructeur.


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


public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}




automatic-properties