Атрибут .NET DefaultValue - PullRequest
       8

Атрибут .NET DefaultValue

49 голосов
/ 25 февраля 2010

Я слышал, что люди говорят несколько раз об атрибуте DefaultValue, включая:

  • Msgstr "Он устанавливает значение свойства прежде, чем что-либо еще его использует".
  • «Это не работает для autoproperties».
  • «Это только для украшения. Вы должны вручную установить фактические значения по умолчанию.»

Что (если есть) правильно? DefaultValue действительно устанавливает значения по умолчанию? Есть ли случаи, когда это не работает? Лучше всего просто не использовать его?

Ответы [ 8 ]

50 голосов
/ 25 февраля 2010

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

Из MSDN:

DefaultValueAttribute не приведет к автоматической инициализации элемента со значением атрибута. Вы должны установить начальное значение в вашем коде.

MSDN - DefaultValueAttribute Class


Редактировать: Как отмечает Роланд, и как уже упоминалось в ответах, этот атрибут также используется конструктором форм

14 голосов
/ 18 июня 2014

Чтобы обновить это через четыре года: В настоящее время установка параметра DefaultValueHandling в JSON.net заставляет DefaultValue работать так, как ожидал @aaron:

[JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[DefaultValue(true)]
public bool AllowUploading { get; set; }
12 голосов
/ 25 февраля 2010

Как и все атрибуты, это метаданные и как таковые «Это только для украшения. Вы должны вручную установить фактические значения по умолчанию». ближайший.

MSDN продолжает говорить о DefaultValueAttribute :

DefaultValueAttribute не приведет к автоматической инициализации элемента со значением атрибута. Вы должны установить начальное значение в вашем коде.

т.е.. Вам все еще нужно, чтобы конструктор соответствовал тому, что вы называете значением по умолчанию, чтобы код, которому он доверяет, все еще работал, например встроенная XML-сериализация, использовала их для определения, сериализовать ли свойство или нет; Точно так же дизайнер форм будет использовать DefaultValue s, чтобы определить, какой код должен быть автоматически сгенерирован.

8 голосов
/ 26 марта 2015

Вы действительно можете "заставить" его работать на любом классе довольно легко.

Сначала вам нужно написать метод расширения объекта в пространстве имен System:

public static class ObjectExtensions
{
    public static void InitializePropertyDefaultValues(this object obj)
    {
        PropertyInfo[] props = obj.GetType().GetProperties();
        foreach (PropertyInfo prop in props)
        {
            var d = prop.GetCustomAttribute<DefaultValueAttribute>();
            if (d != null)
                prop.SetValue(obj, d.Value);
        }
    }
}

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

    public MotherOfMyClasses()
    {
        this.InitializePropertyDefaultValues();
    }
2 голосов
/ 25 февраля 2010

"Он устанавливает значение свойства, прежде чем что-либо еще его использует." -> Нет, значение по умолчанию только для дизайнера. значение по умолчанию не будет выделено в коде конструктора.

"Это не работает для авторежимов." -> Нет

"Это только для украшения. Вы должны вручную установить фактические значения по умолчанию." -> Нет. Из-за Дизайнерской Сериализации. Но вы должны установить его вручную.

1 голос
/ 16 марта 2018

В последних версиях C# вы можете сделать:

public class InitParam
{
    public const int MyInt_Default = 32;
    public const bool MyBool_Default = true;

    [DefaultValue(MyInt_Default)]
    public int MyInt{ get; set; } = MyInt_Default;

    [DefaultValue(MyBool_Default)]
    public bool MyBool{ get; set; } = MyBool_Default;
}
1 голос
/ 26 мая 2010

С MSDN Справка:

AttributeCollection^ attributes = TypeDescriptor::GetProperties( this )[ "MyProperty" ]->Attributes;

/* Prints the default value by retrieving the DefaultValueAttribute 
      * from the AttributeCollection. */
DefaultValueAttribute^ myAttribute = dynamic_cast<DefaultValueAttribute^>(attributes[ DefaultValueAttribute::typeid ]);
Console::WriteLine( "The default value is: {0}", myAttribute->Value );

Мне нужно установить атрибут значения по умолчанию на что-то нестатическое. Как я могу установить его, когда захочу?


Решено путем переопределения функций ShouldSerialize в классе, содержащем свойства.

Пример:

property System::String^ Z {
            System::String^ get(){...}
            void set(System::String^ value) {...}
        }

        bool ShouldSerializeZ() {
            return Z != <call to run time objects>
        }
0 голосов
/ 07 апреля 2014

Вы можете сделать это волшебство с Aspect Orientated Frameworks, как Afterthought или Postsharp.

...