Frage Wie geben Sie einer C # -Auto-Eigenschaft einen Standardwert?


Wie geben Sie einer C # -Auto-Eigenschaft einen Standardwert? Ich benutze entweder den Konstruktor oder stelle die alte Syntax wieder her.

 Verwenden des Konstruktors:

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

Verwenden der normalen Eigenschaftssyntax  (mit einem Standardwert)

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

Gibt es einen besseren Weg?


1419
2017-09-02 21:29


Ursprung


Antworten:


Um in C # 5 und früher automatisch implementierte Eigenschaften mit einem Standardwert zu versehen, müssen Sie dies in einem Konstruktor tun.

Die Möglichkeit, automatische Eigenschaftsinitialisierungen zu verwenden, ist seit C # 6.0 enthalten. Die Syntax lautet:

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

1574
2017-09-02 21:46



Bearbeiten 1/2/15

Mit C # 6 können Sie Auto-Eigenschaften direkt initialisieren (endlich!), Es gibt jetzt andere Antworten im Thread, die das beschreiben.

Für C # 5 und darunter:

Obwohl die beabsichtigte Verwendung des Attributs nicht darin besteht, die Werte der Eigenschaften tatsächlich zu setzen, können Sie die Reflektion immer verwenden, um sie trotzdem festzulegen.

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



Wenn Sie einen Initialwert für eine Variable einfügen, wird dies implizit im Konstruktor ausgeführt.

Ich würde argumentieren, dass diese Syntax in C # bis 5 empfohlen wurde:

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

Dadurch erhalten Sie eine klare Kontrolle über die Auftragswerte.

Ab C # 6 gibt es einen neuen Weg:

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

128
2017-09-04 12:16



DefaultValueAttribute arbeitet NUR im vs-Designer. Es wird die Eigenschaft nicht auf diesen Wert initialisiert.

Sehen DefaultValue-Attribut funktioniert nicht mit meiner Auto-Eigenschaft


73
2017-09-02 22:44



Manchmal benutze ich das, wenn ich nicht möchte, dass es tatsächlich in meiner db gesetzt und beibehalten wird:

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

        set { _name = value; } 
    }
}

Offensichtlich, wenn es keine Zeichenkette ist, könnte ich das Objekt auf Null setzen (double ?, int?) Und prüfen, ob es null ist, einen Standardwert zurückgeben oder den Wert zurückgeben, auf den es gesetzt ist.

Dann kann ich in meinem Repository überprüfen, ob es mein Standard ist und nicht persistieren, oder eine Hintertür einchecken, um vor dem Speichern den wahren Status des Hintergrundwertes zu sehen.

Ich hoffe, das hilft!


48
2017-09-02 23:07



Beginnend mit C # 6.0, Wir können den automatisch implementierten Eigenschaften den Standardwert zuweisen.

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

Wir können auch eine schreibgeschützte automatisch implementierte Eigenschaft erstellen, wie:

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

Sehen: C # 6: Erste Reaktionen, Initialisierer für automatisch implementierte Eigenschaften - Von Jon Skeet


23
2018-04-29 14:40



In C # 6.0 ist das ein Kinderspiel!

Sie können es in der tun Class Deklaration selbst, in den Deklarationen der Eigenschaften.

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



kleines komplettes Beispiel:

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 Version von C # (6,0) und größer, du kannst tun :

Für Readonly-Eigenschaften

public int ReadOnlyProp => 2;

Für beide schreibbare und lesbare Eigenschaften

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

In der aktuellen Version von C # (7,0), Sie können Folgendes tun: (Das Snippet zeigt eher an, wie Sie Expression-Builded-get / set-Accessoren verwenden können, um kompakter zu sein, wenn Sie Backing-Felder verwenden)

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



Meine Lösung besteht darin, ein benutzerdefiniertes Attribut zu verwenden, das die Initialwerteigenschaftsinitialisierung über die Konstanten oder den Property-Typinitialisierer bereitstellt.

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

Um dieses Attribut zu verwenden, müssen Sie eine Klasse von einem speziellen Basisklasseninitialisierer erben oder eine statische Hilfsmethode verwenden:

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

Verwendungsbeispiel:

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

Ausgabe:

Item1
(X=3,Y=4)
StringValue

9
2018-01-17 22:04



Zusätzlich zu der bereits akzeptierten Antwort für das Szenario, in dem Sie eine Standardeigenschaft als a definieren möchten Funktion von anderen Eigenschaften, die Sie verwenden können Ausdruckskörper-Notation auf C # 6.0 (und höher) für noch elegantere und prägnantere Konstrukte wie:

public class Person{

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

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

Sie können das oben genannte auf die folgende Weise verwenden

    var p = new Person();

    p.FullName; // First Last

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

    p.FullName; // Jon Snow

Um die obige Schreibweise "=>" verwenden zu können, muss die Eigenschaft schreibgeschützt sein und Sie dürfen das Schlüsselwort get accessor nicht verwenden.

Details zu MSDN


8
2017-10-30 02:16