【发布时间】:2011-01-20 18:05:35
【问题描述】:
我听说人们对DefaultValue 属性有不同的看法,包括:
- “它在其他任何东西使用它之前设置属性的值。”
- “它不适用于自动属性。”
- “只是为了装饰,你必须手动设置实际的默认值。”
哪个(如果有)是正确的? DefaultValue 是否真的设置了默认值?有没有不起作用的情况?最好不要使用它吗?
【问题讨论】:
标签: c# .net properties attributes
我听说人们对DefaultValue 属性有不同的看法,包括:
哪个(如果有)是正确的? DefaultValue 是否真的设置了默认值?有没有不起作用的情况?最好不要使用它吗?
【问题讨论】:
标签: c# .net properties attributes
我通常使用DefaultValue 的地方是用于序列化/反序列化为 XML 的类。它不在实例化期间设置默认值,并且不影响自动属性。
来自 MSDN:
DefaultValueAttribute 不会导致成员使用属性值自动初始化。您必须在代码中设置初始值。
MSDN - DefaultValueAttribute Class
编辑:正如 Roland 指出的那样,正如其他人在回答中提到的那样,表单设计器也使用了该属性
【讨论】:
“它在其他任何东西使用它之前设置属性的值。” --> 否,默认值仅适用于设计者。默认值不会被序列化到设计器代码中。
“它不适用于自动属性。” --> 没有
"仅用于装饰,您必须手动设置实际默认值。" --> 没有。因为设计器序列化。但必须手动设置。
【讨论】:
与所有属性一样,它是元数据,因此“仅用于装饰。您必须手动设置实际默认值。”最接近。
MSDN 继续谈到 DefaultValueAttribute:
DefaultValueAttribute 不会导致成员使用属性值自动初始化。您必须在代码中设置初始值。
即您仍然需要使构造函数与您所说的默认值相匹配,以便信任它的代码仍然可以工作,例如内置的 XML 序列化将使用它们来确定是否序列化属性;同样,表单设计者将使用DefaultValues 来确定需要自动生成哪些代码。
【讨论】:
来自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>
}
【讨论】:
您可以使用 Afterthought 或 Postsharp 等面向方面的框架来实现这种魔法。
【讨论】:
四年后更新:目前,设置 JSON.net 的 DefaultValueHandling 参数使 DefaultValue 以 @aaron 预期的方式工作:
[JsonProperty("allowUploading",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
[DefaultValue(true)]
public bool AllowUploading { get; set; }
【讨论】:
你实际上可以很容易地“强制”它在任何类上工作。
首先你需要在 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();
}
【讨论】:
Action 对象的静态列表并从 InitializePropertyDefaultValues() 调用它们,这会将反射成本转移到仅在类初始化时进行一次。
在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;
}
【讨论】: