376
votes

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;
}
12
I have converted a feild to a property just so I could set a breakpoint on the setterIan Ringrose
I tend towards making anything that is not private a property because realizing down the road that I must refactor a field into a property has lead to some unnecessary headache. Properties, fields, and methods. Oh My! calls out an incompatibility that has bitten me in the past.Steven Wexler
The prop code snippet makes it fast to create properties. Just type prop then tab.Tono Nam

12 Answers

184
votes

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
    
88
votes

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.

78
votes

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.

67
votes

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.

53
votes

A huge difference that is often overlooked and is not mentioned in any other answer: overriding. You can declare properties virtual and override them whereas you cannot do the same for public member fields.

12
votes

It's all about versioning and API stability. There is no difference, in version 1 - but later, if you decide you need to make this a property with some type of error checking in version 2, you don't have to change your API- no code changes, anywhere, other than the definition of the property.

11
votes

Another advantage of auto-implemented properties over public fields is that you can make set accessors private or protected, providing the class of objects where it was defined better control than that of public fields.

8
votes

There is nothing wrong in making a field public. But remember creating getter/setter with private fields is no encapsulation. IMO, If you do not care about other features of a Property, you might as well make it public.

1
votes

If you decide later to check that the title is unique, by comparing to a collection or a database, you can do that in the property without changing any code that depends on it.

If you go with just a public attribute then you will have less flexibility.

The extra flexibility without breaking the contract is what is most important to me about using properties, and, until I actually need the flexibility, auto-generation makes the most sense.

1
votes

One thing you can do with Fields but not with Properties (or didn't used to be able to ... I'll come to that in a moment) is that Fields can be designated as readonly whereas Properties cannot. So Fields give you a clear way of indicating your intention that a variable is there to be set (from within the constructor) at object-instantiation time only and should not be changed thereafter. Yes, you can set a Property to have a private setter, but that just says "this is not to be changed from outside the class", which is not the same as "this is not to be changed after instantiation" - you can still change it post-instantiation from within the class. And yes you can set the backing field of your property to be readonly, but that moves post-instantiation attempts to change it to being run-time errors rather than compile-time errors. So readonly Fields did something useful which Properties cannot.

However, that changes with C# 9, whereby we get this helpful syntax for Properties:

public string Height { get; init; }

which says "this can get used from outside of the class but it may only be set when the object is initialized", whereupon the readonly advantage of Fields disappears.

0
votes

One thing I find very useful as well as all the code and testing reasons is that if it is a property vs a field is that the Visual Studio IDE shows you the references for a property but not a field.

0
votes

My pov after did some researches

  1. Validation.
  2. Allow overriding the accessor to change the behaviour of a property.
  3. Debugging purpose. We'll be able to know when and what the property change by setting a breakpoint in the accessor.
  4. We can have a field set-only. For instance, public set() and private get(). This is not possible with the public field.

It really gives us more possibility and extensibility.