C# 6.0 Auto-Property Initializers

By | May 26, 2015

Advertisement from Google

C# 6.0The 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


Advertisement from Google

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.

 

Leave a Reply

Your email address will not be published. Required fields are marked *