The next new feature of the C# 6.0 is auto-property initializers and get-only auto property. The main problem that they suppose to solve is immutable type declaration. Before C# 6.0, if you want to create immutable type with properties, you have no possibility to use auto property:
public string Property { get; set; }
So, you were forced to use regular get-only (read-only) property with read-only backing field:
private readonly string prop;
public string Prop { get { return prop; } }
public Ctor()
{
prop = "value";
}
Now, with C# 6.0, you can write:
public string Prop { get; } = "value";
Of course, you can use property initialization not only with read-only auto property. Regular one is also working well:
public string Prop { get; set; } = "value";
The same as static one:
public static string Prop { get; set; } = "value";
You can even use expressions to initialize property:
public string Prop { get; set; } = InitializeProperty();
public static string InitializeProperty()
{
return "value";
}
Internal Implementation
As you may know, C# compiler generates a backing field for auto property. If the property is read-only (get-only) it generates a read-only backing field. In this part nothing changed.
But if you are using auto-property initializer it will also add backing field initialization in the type's constructor. In case of Read\Write auto property:
public int Property { get; set; } = 777;
"Inner" code will look like this:
internal class TestClass
{
private int backingField;
public int Property
{
get { return backingField; }
set { backingField = value; }
}
public TestClass()
{
backingField = 777;
}
}
To check that just look at generated IL:
.class private auto ansi beforefieldinit AutoPropertyInitializer.TestClass
extends [mscorlib]System.Object
{
.field private int32 '<Property>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
.method public hidebysig specialname instance int32
get_Property() cil managed
{
// Getter body ommited
} // end of method TestClass::get_Property
.method public hidebysig specialname instance void
set_Property(int32 'value') cil managed
{
// Setted body ommited
} // end of method TestClass::set_Property
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 18 (0x12)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4 0x309
IL_0006: stfld int32 AutoPropertyInitializer.TestClass::'<Property>k__BackingField'
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: ret
} // end of method TestClass::.ctor
.property instance int32 Property()
{
.get instance int32 AutoPropertyInitializer.TestClass::get_Property()
.set instance void AutoPropertyInitializer.TestClass::set_Property(int32)
} // end of property TestClass::Property
} // end of class AutoPropertyInitializer.TestClass
As you can see, backing field is initializing in the constructor (line IL_0001 and IL_0006).
With get-only auto property you will get almost the same result. Only one difference, backing field will be read-only and you will have no setter (set_Property method):
.field private initonly string '<Property>k__BackingField'
For static auto-property, initialization happens in the static constructor.