.NET DefaultValue 属性

Posted

技术标签:

【中文标题】.NET DefaultValue 属性【英文标题】:.NET DefaultValue attribute 【发布时间】:2011-01-20 18:05:35 【问题描述】:

我听说人们对DefaultValue 属性有不同的看法,包括:

“它在其他任何东西使用它之前设置属性的值。” “它不适用于自动属性。” “只是为了装饰,你必须手动设置实际的默认值。”

哪个(如果有)是正确的? DefaultValue 是否真的设置了默认值?有没有不起作用的情况?最好不要使用它吗?

【问题讨论】:

【参考方案1】:

我通常使用DefaultValue 的地方是用于序列化/反序列化为 XML 的类。它在实例化期间设置默认值,并且不影响自动属性。

来自 MSDN:

DefaultValueAttribute 不会导致成员使用属性值自动初始化。您必须在代码中设置初始值。

MSDN - DefaultValueAttribute Class


编辑:正如 Roland 指出的那样,正如其他人在回答中提到的那样,表单设计器也使用了该属性

【讨论】:

【参考方案2】:

“它在其他任何东西使用它之前设置属性的值。” --> 否,默认值仅适用于设计者。默认值不会被序列化到设计器代码中。

“它不适用于自动属性。” --> 没有

"仅用于装饰,您必须手动设置实际默认值。" --> 没有。因为设计器序列化。但必须手动设置。

【讨论】:

【参考方案3】:

与所有属性一样,它是元数据,因此“仅用于装饰。您必须手动设置实际默认值。”最接近。

MSDN 继续谈到 DefaultValueAttribute:

DefaultValueAttribute 不会导致成员使用属性值自动初始化。您必须在代码中设置初始值。

即您仍然需要使构造函数与您所说的默认值相匹配,以便信任它的代码仍然可以工作,例如内置的 XML 序列化将使用它们来确定是否序列化属性;同样,表单设计者将使用DefaultValues 来确定需要自动生成哪些代码。

【讨论】:

【参考方案4】:

来自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>
        

【讨论】:

【参考方案5】:

您可以使用 Afterthought 或 Postsharp 等面向方面的框架来实现这种魔法。

【讨论】:

【参考方案6】:

四年后更新:目前,设置 JSON.net 的 DefaultValueHandling 参数使 DefaultValue 以 @aaron 预期的方式工作:

[JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[DefaultValue(true)]
public bool AllowUploading  get; set; 

【讨论】:

【参考方案7】:

你实际上可以很容易地“强制”它在任何类上工作。

首先你需要在 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();
    

【讨论】:

不错。如果您为每个 new 类型创建 Action 对象的静态列表并从 InitializePropertyDefaultValues() 调用它们,这会将反射成本转移到仅在类初始化时进行一次。【参考方案8】:

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;

【讨论】:

每个人都应该知道这个方法只适用于自动实现的属性。如果您的 get 和 set 方法中有任何类型的自定义代码,则不能这样做。

以上是关于.NET DefaultValue 属性的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中删除 XML 序列化的 DefaultValue 属性

defaultValue属性包含表单元素的初始值

React-将输入属性从defaultValue设置为value会触发无限循环

强制在来自 NET Web 服务代理类的 SOAP 请求中包含默认值属性属性

React defaultValue 导致过滤功能的行为与预期不同

Antd表单控件的defaultValue 无法动态修改