Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto property initialization IL instruction order

I want to get the default value set on an auto property to do some IL weaving with Fody.

As I understand, the initialization is just a syntactic sugar that sets the backing field in the constructor. So I thought the default value is created with the instructions from the end of the last property's initialization to the stfld instruction that sets the backing field of the current property.

However this assumes the initialization is always done as the first thing in the constructor. Is that a correct assumption? Is there any edge cases to consider such as optimizations?

like image 947
Yusuf Tarık Günaydın Avatar asked Oct 19 '16 18:10

Yusuf Tarık Günaydın


People also ask

Which statement apply to auto-implemented property?

Auto-implemented properties declare a private instance backing field, and interfaces may not declare instance fields. Declaring a property in an interface without defining a body declares a property with accessors that must be implemented by each type that implements that interface.

What is Auto property Initializers?

Auto-property initializers are basically a shortcut to setting the property value in the constructor. I wasn't overly excited about the new feature at first, but I think it makes the intention a lot more clear when you see the initial value on the same line as the auto-implemented property.

What are auto properties?

What is automatic property? Automatic property in C# is a property that has backing field generated by compiler. It saves developers from writing primitive getters and setters that just return value of backing field or assign to it. Instead of writing property like this: public class Dummy.

How do I set default value in property?

Right-click the control that you want to change, and then click Properties or press F4. Click the All tab in the property sheet, locate the Default Value property, and then enter your default value. Press CTRL+S to save your changes.


2 Answers

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.

like image 141
Yusuf Tarık Günaydın Avatar answered Sep 28 '22 07:09

Yusuf Tarık Günaydın


First, a general note: you speak of "the value" as though you could get it from analyzing the IL. This isn't true in general, because the expression could be anything, as long as it doesn't involve this. You can only get the instructions that calculate the value, which may be enough for your application. For an edge case, consider the fact that in particular, the expression may initialize fields other than the backing field of the property:

public int i { get; set; } = s = t = 1;
public static int s { get; set; } = t;
public static int t = 2;

The semantics of this are predictable but not obvious: the default value of s is 0 (t has not been explicitly initialized at this point because initialization happens in declaration order), the default value of t is 2, and the default value of i is 1, with the twist that its initialization, if it occurs, also sets t and then s to 1. Deriving the values from the IL code in this case is not trivial, and even identifying the initializers requires that you consider which stfld/stsfld instructions assign to property backing fields, as opposed to any old field.

Speaking of trivial, if a property is initialized to the default value of the type, the compiler may elide generation of the property initialization altogether since it will be handled by newobj. On the IL level, the following may result in the same code:

int a { get; set; } = 3 / 4;

and

int a { get; set; }

This is an edge case in the sense that what looks like an initializer in code may not be present in the IL at all. If all you're interested in is the value, not whether an explicit initializer was used, this is of course no problem.

like image 43
Jeroen Mostert Avatar answered Sep 28 '22 08:09

Jeroen Mostert