CSharp - 你怎么给一个C# auto property设定一个默认的值?

怎么给一个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;
 }
}

还有更好的方法吗?

时间:

若要在C# 5和更早版本中提供自动实现的属性,必须在构造函数中执行这个操作。

在C# 6.0有自动属性初始化的功能计划 (下一个版本的VB.Net也将拥有它)中包含,C#语法将为:

 

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

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

在内联变量的初始值时,它将隐式地在构造函数中执行。

我认为这种语法是最好的做法:

 

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

因为这可以让您更清楚地控制分配的订单值。

如果我不希望它实际上被设置,并且保存在我的数据库中,那么我会使用它:

 

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

 set { _name = value; } 
 }
}

显然,如果不是字符串,那么我可以使对象为空(double,int? )并检查它是否为空,返回默认值或返回它设置为。

然后我可以在存储库中进行检查,看看是否是默认的,也可以在保存后查看true的状态。

希望有帮助!

小而完整的示例:

 

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

要使用此属性,必须从特殊基类初始值设定项继承类,或者使用静态helper方法:

 

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 string Name { get; set; } = "Some Name" ;

我们还可以创建只读自动实现的属性,如下所示:

 

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

See: C# 6:第一个反应自动实现属性的初始化器-Jon

 

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

...