Initializing C# Auto-Properties

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



Leave a reply



Submit