Initializing C# auto-properties
Update - the answer below was written before C# 6 came along. In C# 6 you can write:
public class Foo
{
public string Bar { get; set; } = "bar";
}
You can also write read-only automatically-implemented properties, which are only writable in the constructor (but can also be given a default initial value):
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
It's unfortunate that there's no way of doing this right now. You have to set the value in the constructor. (Using constructor chaining can help to avoid duplication.)
Automatically implemented properties are handy right now, but could certainly be nicer. I don't find myself wanting this sort of initialization as often as a read-only automatically implemented property which could only be set in the constructor and would be backed by a read-only field.
This hasn't happened up until and including C# 5, but is being planned for C# 6 - both in terms of allowing initialization at the point of declaration, and allowing for read-only automatically implemented properties to be initialized in a constructor body.
When Do C# Auto-Properties Initialize?
That is not an auto property. That's an expression bodied member.
Your implementation of MyProp
computes bool.Parse(Service.Settings["YorN"]);
every time the property getter is called. So in your case, that code is run whenever MyProp
is called, and it's run each time it's called.
If you used an auto property, which would be
public bool MyProp {get;} = bool.Parse(Service.Settings["YorN"]);
Then it would be run after the instance is created, and just before the constructor is called (when other field initializers run). Note that, as this code runs in a field initializer, it cannot use the implicit reference (this
) so if Service
is an instance variable, this won't compile.
C# 6 Auto Initialization Property and the use of backing fields
I'm curious why prior to C#6 IL uses the property definition to initialize. Is there a specific reason for this?
Because setting a value through auto-property initialization and setting the value in a constructor are two different things. They have different behaviours.
Recall that properties are accessor methods which wrap around fields. So this line:
this.First = "Adam";
is equivalent to:
this.set_First("Adam");
You can even see this in Visual Studio! Try writing a method with the signature public string set_First(string value)
in your class and watch as the compiler complains about you stepping on it's toes.
And just like methods, these can be overridden in child classes. Check out this code:
public class PropertyInitialization
{
public virtual string First { get; set; }
public PropertyInitialization()
{
this.First = "Adam";
}
}
public class ZopertyInitalization : PropertyInitialization
{
public override string First
{
get { return base.First; }
set
{
Console.WriteLine($"Child property hit with the value: '{0}'");
base.First = value;
}
}
}
In this example, the line this.First = "Adam"
will call the setter in the child class. Because you're calling a method, remember? If the compiler were to interpret this method call as a direct call to the backing field, it wouldn't end up calling the child setter. The act of compiling your code would change the behaviour of your program. Not good!
Auto-properties are different. Lets change the first example by using an auto-property initializer:
public class PropertyInitialization
{
public virtual string First { get; set; } = "Adam";
}
public class ZopertyInitalization : PropertyInitialization
{
public override string First
{
get { return base.First; }
set
{
Console.WriteLine($"Child property hit with the value: '{0}'");
base.First = value;
}
}
}
With this code, the setter method in the child class will not be called. This is intentional. An auto-property initializer is designed to set the backing field directly. They look and behave like field initializers, which is why we can even use them on properties without setters, like this:
public string First { get; } = "Adam";
There's no setter method here! We would have to directly access the backing field to do this. Auto-properties allow programmers to create immutable values while still being able to benefit from nice syntax.
What is the best way to give a C# auto-property an initial value?
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
, ...
Auto property initialization IL instruction order
I found this pdf file titled Upcoming Features in C# which describes the new language features for C# 6.
Here is the section about auto property initializers (Emphasis is mine):
The initializer directly initializes the backing field; it doesn’t work through the setter of the autoproperty.
The initializers are executed in order as written, just as – and along with – field initializers.
Just like field initializers, auto-property initializers cannot reference ‘this’ – after all they are executed
before the object is properly initialized. This would mean that there aren’t a whole lot of interesting
choices for what to initialize the auto-properties to. However, primary constructors change that. Autoproperty
initializers and primary constructors thus enhance each other.
Since the field initializers and the auto property initializers are treated equally, the following section from C# specification should apply to the auto property initialization as well.
10.11.3 Constructor execution
Variable initializers are transformed into assignment statements, and these assignment statements are executed before the invocation of the base class instance constructor. This ordering ensures that all instance fields are initialized by their variable initializers before any statements that have access to that instance are executed.
...
It is useful to think of instance variable initializers and constructor initializers as statements that are
automatically inserted before the constructor-body.
Is it possible to initialize a property at the point of declaration
No, automatic properties don't allow you to set an initial value.
It's annoying, but such is life. (It's annoying that they can't be readonly, too. But that's a rant for another day.)
EDIT: Both readonly automatically implemented properties and specifying an initial value are slated to be in C# 6.
Difference between (auto) properties initialization syntax in C# 6
Listing 3 is C# 6's equivalent of listing 2, where the backing field is provided under the hood.
Listing 4:
public List<string> Items => new List<string>();
is equivalent to:
public List<string> Items { get { return new List<string>(); } }
which as you can imagine returns a new empty list every time you access the property.
The difference between listings 2/3 and 4 is further explored in this Q&A with an example.
Listing 1 is just an auto property with a getter and a private setter. It's not a readonly property in that you can set it anywhere you can access any of the type's private members. A readonly property (that is, a getter-only property) can only be initialized either in a constructor or in the property declaration, much like a readonly field.
Why can only auto-implemented properties can have initializers in C#?
Pretty sure that is not really how you use get
and set
. Plus your get suffers from self reference. I think this is what you want:
private int _precision = 12;
public int Precision {
get => _precision;
set {
if (value < 0)
_precision = 0;
else if (value > 15)
_precision = 15;
else
_precision = value;
}
}
Do auto implemented properties use private constructors for their initialization
This piece of code is using object initializer syntax in GetSampleProducts
static method.
Object initializers can be used only on types with parameterless constructor, because it's all about syntactic sugar.
This
var p = new Product { Name="West Side Story", Price = 9.99m }
is really translated into this under the hood
var p = new Product();
p.Name = "West Side Story";
p.Price = 9.99m;
It means parameterless constructor is required for var p = new Product();
call. And it will be actually called for each item before the properties are set.
Constructor is private, but as far as GetSampleProducts
is inside Product
type, it can access Product
private members. If you try the same syntax outside of this class it will fail.
So, this
You now have a private parameterless constructor for the sake of the new property-based initialization.
Actually means that constructor isn't used for auto-implemented properties here, it's required for property-based initialization (this term means object initializer), and if you remove it, you will get compilation errors.
Related Topics
Differencebetween a Mutable and Immutable String in C#
Unzip Files Programmatically in .Net
Unauthorised Webapi Call Returning Login Page Rather Than 401
When Do Static Variables Get Initialized in C#
How to Display a Popup from a Webbrowser in Another Window I Created
Cause of Error Cs0161: Not All Code Paths Return a Value
Is It Considered Acceptable to Not Call Dispose() on a Tpl Task Object
Extension Methods Must Be Defined in a Non-Generic Static Class
Views in Separate Assemblies in ASP.NET MVC
Generic Constraints, Where T:Struct and Where T:Class
C# Pass by Value VS. Pass by Reference
Change C# Dllimport Target Code Depending on X64/X86
Predefined Type 'System.Valuetuple'2' Is Not Defined or Imported
Is It Safe to Check Floating Point Values for Equality to 0
How to Replace Multiple White Spaces with One White Space