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

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

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

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

【问题讨论】:

    标签: c# .net properties attributes


    【解决方案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 方法中有任何类型的自定义代码,则不能这样做。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-09-14
                • 2014-07-09
                • 1970-01-01
                • 2010-12-31
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多