Jak nadać C# Auto-właściwość wartości domyślnej?

Jak dać C # Auto-właściwość domyślną wartość? Albo używam konstruktora, albo wracam do starej składni.

Użycie konstruktora:

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

Korzystanie z normalnej składni właściwości (z wartością domyślną)

private string name = "Default Name";
public string Name 
{
    get 
    {
        return name;
    }
    set
    {
        name = value;
    }
}
Czy jest lepszy sposób?
Author: Palantir, 2008-09-03

21 answers

W C # 5 i wcześniejszych, aby nadać auto zaimplementowanym właściwościom domyślną wartość, musisz to zrobić w konstruktorze.

Możliwość posiadania auto property initializers jest włączona od C # 6.0. Składnia to:

public int X { get; set; } = x; // C# 6 or higher
 1658
Author: Darren Kopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 06:59:26

Edit 1/2/15

W C # 6 możesz bezpośrednio inicjalizować auto-właściwości (w końcu!), obecnie w wątku znajdują się inne odpowiedzi, które to opisują.

Dla C # 5 i poniżej:

Chociaż zamierzonym zastosowaniem atrybutu nie jest ustawianie wartości właściwości, możesz użyć reflection, aby zawsze je ustawić...

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
Author: Chuck Rostance,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-12 15:58:24

Gdy wstawisz wartość początkową zmiennej, to i tak będzie to wykonywane w konstruktorze.

Argumentowałbym, że ta składnia była najlepszą praktyką w C# do 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; }
}

Ponieważ daje to wyraźną kontrolę nad przypisanymi wartościami zamówienia.

Od C#6 jest nowy sposób:

public string Name { get; set; } = "Default Name"
 131
Author: Keith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-08 16:23:20

DefaultValueAttribute działa tylko w vs designer. Nie zainicjalizuje właściwości do tej wartości.

Zobacz DefaultValue atrybut nie działa z moją właściwością Auto

 74
Author: Darren Kopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:02

Czasami używam tego, jeśli nie chcę, żeby faktycznie było ustawione i utrzymane w moim db:

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

        set { _name = value; } 
    }
}

Oczywiście jeśli nie jest to ciąg znaków, to mogę sprawić, że obiekt będzie nullable (double?, int? ) i sprawdź, czy jest null, Zwraca wartość domyślną lub zwraca wartość ustawioną.

Następnie mogę sprawdzić w moim repozytorium, aby sprawdzić, czy jest to moja domyślna wartość, a nie persist, lub sprawdzić Backdoor, aby zobaczyć prawdziwy status wartości kopii zapasowej, przed zapisaniem.

Mam nadzieję, że to pomoże!
 49
Author: crucible,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 23:07:27

Począwszy od C # 6.0, możemy przypisać domyślną wartość do automatycznie zaimplementowanych właściwości.

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

Możemy również utworzyć automatycznie zaimplementowaną właściwość tylko do odczytu, taką jak:

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

Patrz: C# 6: pierwsze reakcje, Inicjalizatory Dla automatycznie zaimplementowanych właściwości-by Jon Skeet

 26
Author: Habib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-24 17:22:22

W C # 6.0 to jest bryza!

Można to zrobić w samej deklaracji Class, w oświadczeniach majątkowych.

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
Author: Shiva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 16:34:33

W wersji C #(6.0) & greater możesz zrobić:

Dla właściwości Readonly

public int ReadOnlyProp => 2;

Dla właściwości zapisywalnych i czytelnych

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

W aktualnej wersji C# (7.0), można to zrobić : (fragment raczej pokazuje, jak można użyć get/set accessors expression, aby zrobić jest bardziej kompaktowy, gdy używasz z polami pomocniczymi)

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }
 12
Author: ANewGuyInTown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 05:39:46

Mała pełna Próbka:

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
Author: ghiboz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-21 11:14:17

Moim rozwiązaniem jest użycie niestandardowego atrybutu, który zapewnia inicjalizację właściwości domyślnej wartości za pomocą stałej lub za pomocą inicjalizacji typu właściwości.

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

Aby użyć tego atrybutu, konieczne jest dziedziczenie klasy ze specjalnej bazy class-initializer lub użycie statycznej metody pomocniczej:

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

Przykład użycia:

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

Wyjście:

Item1
(X=3,Y=4)
StringValue
 9
Author: introspected,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-18 07:52:54

Oprócz odpowiedzi już zaakceptowanej, dla scenariusza, w którym chcesz zdefiniować domyślną właściwość jako Funkcja innych właściwości, których możesz użyć zapis ciała ekspresji W C # 6.0 (i wyższych) dla jeszcze bardziej eleganckich i zwięzłych konstrukcji takich jak:

public class Person{

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

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

Możesz użyć powyższego w następujący sposób

    var p = new Person();

    p.FullName; // First Last

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

    p.FullName; // Jon Snow

Aby móc używać powyższej notacji"=>", właściwość musi być tylko do odczytu, a ty nie używasz accesora get słowo kluczowe.

Szczegóły na MSDN

 8
Author: brakeroo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-30 02:16:41

W C # 6 i wyżej możesz po prostu użyć składni:

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

Zauważ, że aby mieć właściwość readonly po prostu pomiń zbiór, tak jak:

public object Foo { get; } = bar;

Możesz również przypisać readonly auto-właściwości z konstruktora.

Wcześniej odpowiedziałem jak poniżej.

Uniknąłbym dodawania domyślnego do konstruktora; zostaw to dla dynamicznych przypisań i uniknąłbym dwóch punktów, w których zmienna jest przypisana(tj. Typ default i w konstruktorze). Zazwyczaj po prostu napisałbym normalna własność w takich przypadkach.

Inną opcją jest zrobienie tego, co ASP.Net wykonuje i definiuje wartości domyślne za pomocą atrybutu:

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

 6
Author: Lex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-17 15:43:26

W konstruktorze. Celem konstruktora jest zainicjowanie jego elementów danych.

 4
Author: RayLoveless,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-18 16:39:49

Próbowałeś użyć DefaultValueAttribute lub w połączeniu z konstruktorem powinno się zresetować i zresetować metody? Czuję, że jedna z tych dwóch metod jest konieczna, jeśli tworzysz klasę, która może pojawić się na powierzchni projektanta lub w siatce właściwości.

 2
Author: OwenP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-02 21:38:10
public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}
 2
Author: FloodMoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-04 20:44:06

Osobiście nie widzę sensu robienia z niego własności w ogóle, jeśli nie zamierzasz robić nic poza własnością. Zostaw to jako pole. Zaletą hermetyzacji tych przedmiotów są tylko czerwone śledzie, ponieważ nie ma za nimi nic do hermetyzacji. Jeśli kiedykolwiek będziesz musiał zmienić podstawową implementację, nadal możesz refaktorować je jako właściwości bez łamania zależnego kodu.

Hmm... może to będzie temat jego własnego pytania później

 1
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-03 03:43:20

Aby wyjaśnić, tak, musisz ustawić domyślne wartości w konstruktorze dla obiektów pochodnych klas. Będziesz musiał upewnić się, że konstruktor istnieje z odpowiednim modyfikatorem dostępu do konstrukcji, gdzie jest używany. Jeżeli obiekt nie jest utworzony, np. nie posiada konstruktora (np. metody statyczne), wtedy pole może ustawić wartość domyślną. Rozumowanie tutaj jest takie, że sam obiekt zostanie utworzony tylko raz i nie tworzysz go instancyjnie.

@Darren Kopp-dobra odpowiedź, czysta i zgadza się. Dla przypomnienia, można pisać konstruktory dla metod abstrakcyjnych. Po prostu musisz uzyskać do nich dostęp z klasy bazowej podczas pisania konstruktora:

Konstruktor w klasie bazowej:

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

Konstruktor w pochodnej / betonowej / podklasie:

public SubClass() : base() { }

Chodzi o to, że zmienna instancji pobrana z klasy bazowej może zakopać nazwę pola podstawowego. Ustawienie bieżącej wartości obiektu instancyjnego za pomocą "this."pozwoli Ci poprawnie uformować swój obiekt z odnosi się do bieżącej instancji i wymaganych poziomów uprawnień (modyfikatory dostępu), w których tworzysz jej instancję.

 1
Author: Zack Jannsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-07 14:26:41

Użyj konstruktora, ponieważ "gdy konstruktor jest skończony, budowa powinna być skończona". właściwości są jak stany, które posiadają Twoje klasy, gdybyś musiał zainicjować stan domyślny, zrobiłbyś to w konstruktorze.

 1
Author: Preet Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
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
Author: Nag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 13:55:16

Myślę, że to zrobiłoby to dla Ciebie, dając komuś default false.

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

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

        SomeFlag = value;        
    }
}
 -2
Author: user3076134,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-06 21:50:59

Initialize in line, używanie konstruktorów do inicjalizacji jest złą praktyką i doprowadzi później do kolejnych zmian.

 -3
Author: dbobrowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-13 19:13:27