Public Fields versus Automatic Properties

We're often told we should protect encapsulation by making getter and setter methods (properties in C#) for class fields, instead of exposing the fields to the outside world.

But there are many times when a field is just there to hold a value and doesn't require any computation to get or set. For these we would all do this number:

public class Book
{
    private string _title;

    public string Title
    {
          get => _title; 
          set => _title = value;
    }
}

Well, I have a confession, I couldn't bear writing all that (really, it wasn't having to write it, it was having to look at it), so I went rogue and used public fields.

Then along comes C# 3.0 and I see they added automatic properties:

public class Book
{
    public string Title { get; set; } 
}

Which is tidier, and I'm thankful for it, but really, what's so different than just making a public field?

public class Book
{
    public string Title;
}

In a related question I had some time ago, there was a link to a posting on Jeff's blog, explaining some differences.

Properties vs. Public Variables

  • Reflection works differently on variables vs. properties, so if you rely on reflection, it's easier to use all properties.
  • You can't databind against a variable.
  • Changing a variable to a property is a breaking change. For example:

    TryGetTitle(out book.Title); // requires a variable
    

Ignoring the API issues, the thing I find most valuable about using a property is debugging.

The CLR debugger does not support data break points (most native debuggers do). Hence it's not possible to set a break point on the read or write of a particular field on a class. This is very limiting in certain debugging scenarios.

Because properties are implemented as very thin methods, it is possible to set breakpoints on the read and write of their values. This gives them a big leg up over fields.


Changing from a field to a property breaks the contract (e.g. requires all referencing code to be recompiled). So when you have an interaction point with other classes - any public (and generally protected) member, you want to plan for future growth. Do so by always using properties.

It's nothing to make it an auto-property today, and 3 months down the line realize you want to make it lazy-loaded, and put a null check in the getter. If you had used a field, this is a recompile change at best and impossible at worst, depending on who & what else relies on your assemblies.


Just because no one mentioned it: You can't define fields on Interfaces. So, if you have to implement a specific interface which defines properties, auto-properties sometimes are a really nice feature.