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 *