Vraag Hoe geef je een C # Auto-Property een standaardwaarde?


Hoe geef je een C # Auto-Property een standaardwaarde? Ik gebruik de constructor of ga terug naar de oude syntaxis.

 De Constructor gebruiken:

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

Normale eigenschapsyntaxis gebruiken  (met een standaardwaarde)

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

Is er een betere manier?


1419
2017-09-02 21:29


oorsprong


antwoorden:


In C # 5 en eerder, om automatisch geïmplementeerde eigenschappen een standaardwaarde te geven, moet je dit in een constructor doen.

De mogelijkheid om automatische eigenschap-initializers te hebben is opgenomen sinds C # 6.0. De syntaxis is:

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

1574
2017-09-02 21:46



Bewerk 1/2/15

Met C # 6 kun je auto-eigenschappen direct (ten slotte!) Initialiseren, er zijn nu andere antwoorden in de thread die dat beschrijven.

Voor C # 5 en lager:

Hoewel het beoogde gebruik van het kenmerk niet is om de waarden van de eigenschappen daadwerkelijk in te stellen, kunt u reflectie gebruiken om ze altijd toch in te stellen ...

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

242
2018-06-22 18:14



Wanneer u een beginwaarde voor een variabele lijnt, wordt deze hoe dan ook impliciet in de constructor gedaan.

Ik zou zeggen dat deze syntaxis de beste methode was in C # tot 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; }
}

Omdat dit u een duidelijk overzicht geeft van de orderwaarden die zijn toegewezen.

Vanaf C # 6 is er een nieuwe manier:

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

128
2017-09-04 12:16



DefaultValueAttribute werkt ALLEEN in de ontwerper van vs. Het zal de eigenschap niet naar die waarde initialiseren.

Zien Het DefaultValue-kenmerk werkt niet met mijn Auto-eigenschap


73
2017-09-02 22:44



Soms gebruik ik dit, als ik niet wil dat het daadwerkelijk wordt ingesteld en blijft bestaan ​​in mijn database:

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

        set { _name = value; } 
    }
}

Het is duidelijk dat als het geen string is, ik het object nullable (double ?, int?) Maak en controleer of het object leeg is, een standaard retourneert of de waarde retourneert waarnaar het is ingesteld.

Vervolgens kan ik in mijn repository een controle uitvoeren om te zien of dit mijn standaard is en niet aanhouden, of een backdoor-check uitvoeren om de ware status van de waarde van de back-up te zien, voordat deze wordt opgeslagen.

Ik hoop dat het helpt!


48
2017-09-02 23:07



Beginnend met C # 6.0, We kunnen de standaardwaarde toewijzen aan automatisch geïmplementeerde eigenschappen.

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

We kunnen ook alleen-lezen automatisch geïmplementeerde eigenschappen maken, zoals:

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

Zien: C # 6: Eerste reacties, Initializers voor automatisch geïmplementeerde eigenschappen - Door Jon Skeet


23
2018-04-29 14:40



In C # 6.0 is dit een eitje!

Je kunt het in de Class verklaring zelf, in de verklaringen van de eigendomsverklaring.

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

17
2017-07-25 19:35



kleine complete sample:

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
2018-06-17 07:44



In versie van C # (6.0) en groter, je kunt doen:

Voor Readonly-eigenschappen

public int ReadOnlyProp => 2;

Voor zowel beschrijfbare als leesbare eigenschappen

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

In de huidige versie van C # (7.0), je kunt doen: (Het fragment geeft eerder aan hoe je expression bodied get / set accessors kunt gebruiken om compacter te maken bij gebruik van achtergrondvelden)

private string label = "Default Value";

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

11
2018-03-15 01:07



Mijn oplossing is om een ​​aangepast kenmerk te gebruiken dat initialisatie van de standaardwaarde-eigenschap biedt door een constante of met behulp van de initialisator van het eigenschaptype.

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

Om dit attribuut te gebruiken, is het noodzakelijk om een ​​klasse te erven van een speciale basisklasse-initializer of een statische helper-methode te gebruiken:

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

Gebruik voorbeeld:

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

Output:

Item1
(X=3,Y=4)
StringValue

9
2018-01-17 22:04