Desugaring auto-implemented properties

What do you prefer: a field or a property? Most object oriented gurus will tell you that a property should be preferred. But do you sometimes feel that writing all those properties in C# is a waste of time?

Of course you know that using properties is important to encapsulate the inner workings of your class. By using accessors and mutators you hide the implementation details of your class and you can add logic like validation or notifications. If you would convert a field to a property you would change the metadata of your assembly and depending applications would have to be recompiled.

But most of your properties have empty getters and setters, but still you have to create a private field and a property with both a get and set accessor like this:

   1:  class Foo
   2:  {
   3:      private int _bar;
   4:   
   5:      public int Bar
   6:      {
   7:          get { return _bar; }
   8:          set { _bar = value; }
   9:      }
  10:  }

When looking at your Foo class in Ildasm you see the following:

image

As you can see, your property is emitted as get_Bar and set_Bar method. This is how your property actually works. Every place where you read from a property is replaced by a call to get_Bar. Writing is replaced with set_Bar. So here you see an example of syntactic sugar! Instead of having to write the get_Bar and set_Bar method yourself, the compiler helps you by offering a nice syntax for properties.

Going auto

This is all nice, but what if you don’t have to add any extra code to the getter or setter? This is where auto-implemented properties show their value. An auto-implemented property is syntactic sugar that allows you to write a plain property in a simple way:

   1:  class Foo
   2:  {
   3:      public int Bar { get; set; }
   4:  }

You can specify different accessibility levels for your get and set method, for example by marking the setter as read-only:

public int Bar { get; private set; }

As you can see, you don’t have to specify a backing field and you don’t have to write the code for the getter and setter. This is all nice, but how does it work behind the scenes?

Using Ildasm on auto-implemented properties

We can inspect the IL that’s being generated by using Ildasm on the Foo class. This gives you the following result:

image
You still have the get_Bar and set_Bar method but now you also have a <Bar>k_BackingField field. In C# this would be an illegal name for a field but in IL code it’s perfectly legal. The compiler uses this naming convention to make sure that generated fields don’t conflict with any user defined elements. It also decorates the field with the CompilerGeneratedAttribute. You can verify that this field really exists by using reflection:

   1:  Foo foo = new Foo();
   2:   
   3:  Console.WriteLine(foo.Bar); // Displays 0
   4:   
   5:  var fields = foo.GetType().GetFields(
   6:      BindingFlags.Instance | BindingFlags.NonPublic);
   7:  var field = fields[0];
   8:   
   9:  Console.WriteLine(field.Name); // <Bar>k_BackingField
  10:  field.SetValue(foo, 42);
  11:   
  12:  Console.WriteLine(foo.Bar); // Displays 42

As you can see, the field really exists and when you know it’s name you can even access it through reflection. Of course this isn’t a recommended way to start juggling with your auto-implemented properties. Normally, the backing field of an auto-implemented property is not accessible from your C# code. This also explains why an auto-implemented property requires both a getter and a setter. Since you can’t access the backing field from normal code, it would be useless to have an auto-implemented property with only a getter.

So that’s how auto-implemented properties work. By using them, you get a syntax that’s almost as concise as using a field but offers you the possibility of switching to a full property whenever you want. And by desugaring your code, you discovered that an auto-implemented property is just a get and set method with a private backing field.

Questions? Remarks? Please leave a comment!

Wouter de Kort works as a lead architect and consultant. He helps organizations stay on the cutting edge of software development. Wouter focuses on DevOps. He loves solving complex problems and helping other developers to grow. Wouter authored the book DevOps on the Microsoft stack and a couple of other books. Wouter is a Microsoft MVP and an ALM Ranger. You can find him on Twitter (@wouterdekort), on his blog at wouterdekort.com and at the various conferences where Wouter speaks.

Share

Leave a Reply

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

Post comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.