代码之家  ›  专栏  ›  技术社区  ›  bentford Marko Hlebar

如何给C auto属性一个默认值?

  •  1587
  • bentford Marko Hlebar  · 技术社区  · 16 年前

    如何给C auto属性一个默认值?我要么使用构造函数,要么恢复到旧的语法。

    使用构造函数:

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

    有更好的方法吗?

    22 回复  |  直到 6 年前
        1
  •  1836
  •   Shishir Gupta    9 年前

    在C 5和更早的版本中,为了给自动实现的属性一个默认值,您必须在构造函数中这样做。

    自C 6.0以来,包含自动属性初始值设定项的功能。语法是:

    public int X { get; set; } = x; // C# 6 or higher
    
        2
  •  262
  •   Ajay2707 calm    6 年前

    2015年1月2日编辑

    C 6 :

    使用C 6,您可以直接初始化自动属性(最后!)现在,在描述这个问题的线索中还有其他答案。

    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; }
    }
    
        3
  •  140
  •   Keith    9 年前

    当您内联变量的初始值时,它无论如何都将在构造函数中隐式完成。

    我认为这种语法是C到5的最佳实践:

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

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

    从C 6开始,有一种新的方法:

    public string Name { get; set; } = "Default Name"
    
        4
  •  78
  •   Community CDub    8 年前

    默认值属性仅在vs设计器中有效。它不会将属性初始化为该值。

    DefaultValue attribute is not working with my Auto Property

        5
  •  53
  •   crucible    16 年前

    有时我会使用这个,如果我不希望它在我的数据库中被实际设置和持久化:

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

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

    然后我可以在我的存储库中进行一次检查,以查看它是否是我的默认值并且不持久,或者在保存之前进行一次后门检入以查看备份值的真实状态。

    希望有帮助!

        6
  •  34
  •   Habib    9 年前

    从C 6.0开始 ,我们可以为自动实现的属性分配默认值。

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

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

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

    见: C# 6: First reactions , Initializers for automatically implemented properties - By Jon Skeet

        7
  •  32
  •   Graham francescalus    7 年前

    在C 6.0中,这是一种轻风!

    你可以在 Class 声明本身,在属性声明语句中。

    public class Coordinate
    { 
        public int X { get; set; } = 34; // get or set auto-property with initializer
    
        public int Y { get; } = 89;      // read-only auto-property with initializer
    
        public int Z { get; }            // read-only auto-property with no initializer
                                         // so it has to be initialized from constructor    
    
        public Coordinate()              // .ctor()
        {
            Z = 42;
        }
    }
    
        8
  •  20
  •   ANewGuyInTown    7 年前

    在版本中 C(6.0)及以上 你可以这样做:

    用于只读属性

    public int ReadOnlyProp => 2;
    

    对于可写和可读属性

    public string PropTest { get; set; } = "test";
    

    在的当前版本中 C~(7) ,您可以这样做:(代码段显示了如何使用表达式bodied get/set访问器,使其在与支持字段一起使用时更紧凑)

    private string label = "Default Value";
    
    // Expression-bodied get / set accessors.
    public string Label
    {
       get => label;
       set => this.label = value; 
     }
    
        9
  •  12
  •   brakeroo    8 年前

    除了已经接受的答案之外,对于要将默认属性定义为 功能 您可以使用的其他属性 表达式体符号 在C 6.0(及更高版本)上,提供更优雅、更简洁的结构,如:

    public class Person{
    
        public string FullName  => $"{First} {Last}"; // expression body notation
    
        public string First { get; set; } = "First";
        public string Last { get; set; } = "Last";
    }
    

    您可以按以下方式使用上面的内容

        var p = new Person();
    
        p.FullName; // First Last
    
        p.First = "Jon";
        p.Last = "Snow";
    
        p.FullName; // Jon Snow
    

    为了能够使用上面的“=>!”符号,属性必须是只读的,并且不使用get accessor关键字。

    细节 MSDN

        10
  •  12
  •   Mikko Viitala    8 年前

    小完整样本:

    using System.ComponentModel;
    
    private bool bShowGroup ;
    [Description("Show the group table"), Category("Sea"),DefaultValue(true)]
    public bool ShowGroup
    {
        get { return bShowGroup; }
        set { bShowGroup = value; }
    }
    
        11
  •  9
  •   introspected    12 年前

    我的解决方案是使用自定义属性,该属性通过常量或使用属性类型初始值设定项提供默认值属性初始化。

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

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

    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
    
        12
  •  8
  •   Lex    7 年前

    在C 6及以上版本中,您只需使用以下语法:

    public object Foo { get; set; } = bar;
    

    注意要有一个 readonly 属性只省略集合,因此:

    public object Foo { get; } = bar;
    

    您也可以分配 只读 来自构造函数的自动属性。

    在此之前,我的回答如下。

    我将避免向构造函数中添加默认值;将其留给动态赋值,并避免在变量被赋值时有两个点(即类型默认值和构造函数中)。在这种情况下,通常我只写一个普通属性。

    另一个选项是执行ASP.NET的操作,并通过属性定义默认值:

    http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx

        13
  •  4
  •   RayLoveless    8 年前

    在构造函数中。构造函数的目的是初始化它的数据成员。

        14
  •  3
  •   ComeIn    6 年前
    private string name;
    public string Name 
    {
        get 
        {
            if(name == null)
            {
                name = "Default Name";
            }
            return name;
        }
        set
        {
            name = value;
        }
    }
    
        15
  •  2
  •   OwenP    16 年前

    你试过使用 DefaultValueAttribute ShouldSerialize and Reset methods 与建造师一起?我觉得这两个方法中的一个是必要的,如果你正在创建一个类,它可能会出现在设计器图面或属性网格中。

        16
  •  2
  •   FloodMoo    10 年前
    public Class ClassName{
        public int PropName{get;set;}
        public ClassName{
            PropName=0;  //Default Value
        }
    }
    
        17
  •  1
  •   Joel Coehoorn    16 年前

    就我个人而言,如果你不打算做任何超越汽车业的事情,我根本就不认为这是一种财产。把它当作一个场。这些项目的封装好处只是红鲱鱼,因为它们后面没有什么可以封装的。如果您需要更改底层实现,您仍然可以自由地将它们重构为属性,而不破坏任何依赖代码。

    隐马尔可夫模型。。。也许这将是以后它自己的问题的主题

        18
  •  1
  •   Johnie Karr    11 年前

    要澄清,是的,您需要在类派生对象的构造函数中设置默认值。您将需要确保构造函数存在,并在使用时为构造提供适当的访问修饰符。如果对象没有实例化,例如它没有构造函数(例如静态方法),那么可以通过字段设置默认值。这里的理由是对象本身只创建一次,而您不实例化它。

    @Darren Kopp-回答正确、干净、正确。重复一下,您可以为抽象方法编写构造函数。在编写构造函数时,只需要从基类访问它们:

    基类的构造函数:

    public BaseClassAbstract()
    {
        this.PropertyName = "Default Name";
    }
    

    派生/混凝土/子类的构造函数:

    public SubClass() : base() { }
    

    这里的要点是,从基类中提取的实例变量可能会隐藏您的基字段名。使用“this.”设置当前实例化的对象值将允许您根据当前实例和所需的权限级别(访问修饰符)正确地构造对象。

        19
  •  1
  •   Preet Singh    9 年前

    使用构造函数是因为“当构造函数完成时,应该完成构造”。属性类似于类所持有的状态,如果必须初始化默认状态,则可以在构造函数中这样做。

        20
  •  0
  •   Bridge user2173966    10 年前
    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; }
    }
    
        21
  •  -2
  •   user3076134    11 年前

    我认为这对你来说是个错误。

    private bool _SomeFlagSet = false;
    public bool SomeFlag
    {
        get
        {
            if (!_SomeFlagSet)
                SomeFlag = false;        
    
            return SomeFlag;
        }
        set
        {
            if (!_SomeFlagSet)
                _SomeFlagSet = true;
    
            SomeFlag = value;        
        }
    }
    
        22
  •  -5
  •   dbobrowski    12 年前

    在行中初始化,使用构造函数初始化是不好的做法,稍后会导致更多的中断更改。