What is the best way to give a C# auto-property an initial value?

前端 未结 22 3032
死守一世寂寞
死守一世寂寞 2020-11-22 02:48

How do you give a C# auto-property an initial value?

I either use the constructor, or revert to the old syntax.

Using the Constructor:

相关标签:
22条回答
  • 2020-11-22 03:18

    I know this is an old question, but it came up when I was looking for how to have a default value that gets inherited with the option to override, I came up with

    //base class
    public class Car
    {
        public virtual string FuelUnits
        {
            get { return "gasoline in gallons"; }
            protected set { }
        }
    }
    //derived
    public class Tesla : Car
    {
        public override string FuelUnits => "ampere hour";
    }
    
    0 讨论(0)
  • 2020-11-22 03:20

    My solution is to use a custom attribute that provides default value property initialization by constant or using property type initializer.

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

    To use this attribute it's necessary to inherit a class from special base class-initializer or use a static helper method:

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

    Usage example:

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

    Output:

    Item1
    (X=3,Y=4)
    StringValue
    
    0 讨论(0)
  • 2020-11-22 03:22

    In the constructor. The constructor's purpose is to initialized it's data members.

    0 讨论(0)
  • 2020-11-22 03:23

    You can simple put like this

    public sealed  class Employee
    {
        public int Id { get; set; } = 101;
    }
    
    0 讨论(0)
  • 2020-11-22 03:24

    In C# 5 and earlier, to give auto implemented properties an initial value, you have to do it in a constructor.

    Since C# 6.0, you can specify initial value in-line. The syntax is:

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

    DefaultValueAttribute is intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in designed object, initial value is the default value).

    At compile time DefaultValueAttribute will not impact the generated IL and it will not be read to initialize the property to that value (see DefaultValue attribute is not working with my Auto Property).

    Example of attributes that impact the IL are ThreadStaticAttribute, CallerMemberNameAttribute, ...

    0 讨论(0)
  • 2020-11-22 03:26

    To clarify, yes, you need to set default values in the constructor for class derived objects. You will need to ensure the constructor exists with the proper access modifier for construction where used. If the object is not instantiated, e.g. it has no constructor (e.g. static methods) then the default value can be set by the field. The reasoning here is that the object itself will be created only once and you do not instantiate it.

    @Darren Kopp - good answer, clean, and correct. And to reiterate, you CAN write constructors for Abstract methods. You just need to access them from the base class when writing the constructor:

    Constructor at Base Class:

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

    Constructor at Derived / Concrete / Sub-Class:

    public SubClass() : base() { }
    

    The point here is that the instance variable drawn from the base class may bury your base field name. Setting the current instantiated object value using "this." will allow you to correctly form your object with respect to the current instance and required permission levels (access modifiers) where you are instantiating it.

    0 讨论(0)
提交回复
热议问题