Как вы даете авто-свойству C# значение по умолчанию?



Как вы даете авто-свойству C# значение по умолчанию? Я либо использую конструктор, либо возвращаюсь к старому синтаксису.



С помощью конструктора:



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


используя стандартный синтаксис (значение по умолчанию)



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


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

676   21  

21 ответов:

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

возможность иметь инициализаторы автоматического свойства включена с C# 6.0. Синтаксис:

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

изменить 1/2/15

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

для C# 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; }
}

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

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

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

С C#6 есть новый способ:

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

DefaultValueAttribute работает только в vs designer. Он не будет инициализировать свойство к этому значению.

посмотреть атрибут DefaultValue не работает с моим свойством Auto

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

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

        set { _name = value; } 
    }
}

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

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

надеюсь, что помогает!

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

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

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

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

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

В C# 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;
    }
}

В версии в C# (6.0) & больше, вы можете сделать :

для свойства readonly

public int ReadOnlyProp => 2;

для обоих записываемых и читаемых свойств

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

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

private string label = "Default Value";

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

мало полный пример:

using System.ComponentModel;

private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
    get { return bShowGroup; }
    set { bShowGroup = value; }
}

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

[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

в дополнение к уже принятому ответу, для сценария, когда вы хотите определить свойство по умолчанию как функции других свойств, вы можете использовать выражения обозначения кузова на C#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

В C# 6 и выше, вы можете просто использовать следующий синтаксис:

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

обратите внимание, что у readonly свойство просто опустить набор, как так:

public object Foo { get; } = bar;

вы также можете назначить readonly авто-недвижимость от застройщика.

до этого я ответил ниже.

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

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

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

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

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

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

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

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

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

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

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

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

конструктор в производном / конкретном / подклассе:

public SubClass() : base() { }

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

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

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

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

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

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

        SomeFlag = value;        
    }
}

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

Comments

    Ничего не найдено.