Каков наилучший способ дать авто-свойству С# начальное значение?

Как вы даете авто-свойству С# начальное значение?

Я либо использую конструктор, либо возвращаюсь к старому синтаксису.

 Использование конструктора:

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

Использование обычного синтаксиса свойств (с начальным значением)

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

Есть ли лучший способ?

Ответы

Ответ 1

В С# 5 и ранее, чтобы дать автоматически реализованным свойствам начальное значение, вы должны сделать это в конструкторе.

Начиная с С# 6.0, вы можете указать начальное значение в строке. Синтаксис:

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

DefaultValueAttribute предназначен для использования конструктором VS (или любым другим потребителем) для указания значения по умолчанию, а не исходного значения. (Даже если в разработанном объекте начальное значение является значением по умолчанию).

Во время компиляции DefaultValueAttribute не повлияет на сгенерированный IL, и он не будет считан, чтобы инициализировать свойство этим значением (см. Атрибут DefaultValue не работает с моим автоматическим свойством).

Примером атрибутов, влияющих на IL, являются ThreadStaticAttribute, CallerMemberNameAttribute,...

Ответ 2

Отредактировано 1/2/15

С# 6:

С С# 6 вы можете инициализировать авто-свойства напрямую (наконец-то!), Теперь в ветке есть другие ответы, которые описывают это.

С# 5 и ниже:

Хотя предполагаемое использование атрибута не в том, чтобы фактически устанавливать значения свойств, вы можете использовать отражение, чтобы всегда устанавливать их в любом случае...

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

Ответ 3

Когда вы встраиваете начальное значение для переменной, оно будет выполняться неявно в конструкторе.

Я бы сказал, что этот синтаксис был наилучшей практикой в ​​С# до 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; }
}

Так как это дает вам четкое управление значениям порядка.

С С# 6 существует новый способ:

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

Ответ 5

Иногда я использую это, если я не хочу, чтобы он действительно был установлен и сохранялся в моем db:

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

        set { _name = value; } 
    }
}

Очевидно, если это не строка, я могу сделать объект нулевым (double?, int?) и проверить, не null ли он, вернуть значение по умолчанию или вернуть значение, которое оно установило.

Затем я могу сделать чек в моем репозитории, чтобы увидеть, если он мой по умолчанию и не сохраняется, или сделать проверку бэкдор, чтобы увидеть истинный статус резервного значения, прежде чем сохранять.

Надеюсь, что это поможет!

Ответ 6

В С# 6.0 это легкий ветерок!

Вы можете сделать это в самом объявлении Class в заявлениях объявления свойств.

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

Ответ 7

Начиная с С# 6.0, мы можем назначить значение по умолчанию для автоматически реализованных свойств.

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

Мы также можем создать автоматическое свойство, доступное только для чтения, например:

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

Смотрите: С# 6: первые реакции, инициализаторы для автоматически реализованных свойств - Jon Skeet

Ответ 8

В версии С# (6.0) и выше вы можете:

Для свойств Readonly

public int ReadOnlyProp => 2;

Для обоих свойств Writable и Readable

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

В текущей версии С# (7.0) вы можете сделать: (фрагмент скорее показывает, как вы можете использовать выражения с расширенными функциями get/set, чтобы сделать более компактным при использовании с полями поддержки)

private string label = "Default Value";

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

Ответ 9

В дополнение к уже принятому ответу, для сценария, когда вы хотите определить свойство по умолчанию как функцию от других свойств, вы можете использовать нотацию тела выражения на С# 6.0 (и выше) для еще более элегантных и лаконичных конструкций, таких как:

public class Person{

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

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

Вы можете использовать вышеуказанное следующим образом

    var p = new Person();

    p.FullName; // First Last

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

    p.FullName; // Jon Snow

Чтобы использовать вышеуказанную нотацию "=>", свойство должно быть доступно только для чтения, и вы не используете ключевое слово get accessor.

Подробности на MSDN

Ответ 10

маленький полный образец:

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

Моим решением является использование настраиваемого атрибута, который инициализирует инициализацию значения по умолчанию константой или использует инициализатор типа свойства.

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

Чтобы использовать этот атрибут, необходимо наследовать класс из специального базового класса-инициализатора или использовать статический вспомогательный метод:

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

Пример использования:

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

Вывод:

Item1
(X=3,Y=4)
StringValue

Ответ 12

В С# 6 и выше вы можете просто использовать синтаксис:

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

Обратите внимание, что для того, чтобы иметь свойство только для readonly просто опустите набор, как показано ниже:

public object Foo { get; } = bar;

Вы также можете назначить только свойства для readonly из конструктора.

До этого я отвечал как ниже.

Я бы не стал добавлять конструктор по умолчанию; оставьте это для динамических назначений и избегайте двух точек, в которых назначается переменная (то есть тип по умолчанию и в конструкторе). Обычно я бы просто написал нормальное свойство в таких случаях.

Еще один вариант - сделать то, что делает ASP.Net, и определить значения по умолчанию с помощью атрибута:

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

Ответ 13

В конструкторе. Цель конструктора - инициализировать его членами данных.

Ответ 14

Вы можете просто поставить вот так

public sealed  class Employee
{
    public int Id { get; set; } = 101;
}

Ответ 15

Вы пытались использовать DefaultValueAttribute или ShouldSerialize и Reset в сочетании с конструктором? Я чувствую, что один из этих двух методов необходим, если вы создаете класс, который может отображаться на поверхности конструктора или в сетке свойств.

Ответ 16

private string name;
public string Name 
{
    get 
    {
        if(name == null)
        {
            name = "Default Name";
        }
        return name;
    }
    set
    {
        name = value;
    }
}

Ответ 17

Лично я не вижу смысла делать его собственностью вообще, если вы не собираетесь делать что-либо вообще за пределами авто-собственности. Просто оставьте это как поле. Преимущество инкапсуляции для этого элемента - просто красные сельди, потому что ничего не позади, чтобы инкапсулировать. Если вам когда-либо понадобится изменить базовую реализацию, вы по-прежнему можете реорганизовать их как свойства без нарушения какого-либо зависимого кода.

Хм... может быть, это будет вопрос его собственного вопроса позже

Ответ 18

Чтобы уточнить, да, вам нужно установить значения по умолчанию в конструкторе для объектов класса. Вам нужно будет убедиться, что конструктор существует с соответствующим модификатором доступа для построения, где он используется. Если объект не создается, например. он не имеет конструктора (например, статические методы), тогда значение по умолчанию может быть задано полем. Примером здесь является то, что сам объект будет создан только один раз, и вы не создадите его.

@Даррен Копп - хороший ответ, чистый и правильный. И, повторяю, вы можете написать конструкторы для абстрактных методов. Вам просто нужно получить к ним доступ из базового класса при написании конструктора:

Конструктор в базовом классе:

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

Конструктор в Derived/Concrete/Sub-Class:

public SubClass() : base() { }

Дело здесь в том, что переменная экземпляра, взятая из базового класса, может похоронить имя вашего базового поля. Установка текущего значения объекта-объекта с помощью "this". позволит вам правильно сформировать ваш объект в отношении текущего экземпляра и требуемых уровней разрешений (модификаторы доступа), в которых вы его создаете.

Ответ 19

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

Ответ 20

Используйте конструктор, потому что "Когда конструктор закончен, конструкция должна быть закончена". свойства похожи на состояния, которые хранятся ваши классы, если вам нужно было инициализировать состояние по умолчанию, вы сделали бы это в своем конструкторе.

Ответ 21

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

Ответ 22

Я думаю, что это сделало бы это для ya givng SomeFlag по умолчанию false.

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

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

        SomeFlag = value;        
    }
}

Ответ 23

Введите Prop и нажмите кнопку "TAB" и Visual Studio. Предложите вам следующий код,

public int MyProperty { get; set; }

после того, как вы сможете изменить модификатор, тип данных, имя и легко назначить набор и получить значения.

если вы должны использовать некоторую переменную в другом классе, вы можете использовать как follwing,

public static int MyProperty { get; set; }

в коде вы можете назначить переменную

MyProperty=1;

в другом классе вы можете использовать,

MessageBox.Show(Classname.MyProperty);

Ответ 24

инициализируется в строке, использование конструкторов для инициализации - это плохая практика и приведет к более резким изменениям позже.