Public Fields versus Automatic Properties

77,059

Solution 1

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
    

Solution 2

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.

Solution 3

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.

Solution 4

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.

Solution 5

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.

Share:
77,059
I. J. Kennedy
Author by

I. J. Kennedy

[email protected]

Updated on July 08, 2022

Comments

  • I. J. Kennedy
    I. J. Kennedy almost 2 years

    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;
    }
    
  • Steven
    Steven over 12 years
    "Changing a variable to a property is a breaking change." This of course only applies when writing a reusable library, which most developers are not doing.
  • KeithS
    KeithS over 11 years
    Also, properties, even auto-properties, can be virtual, where fields cannot. So, a base class can have a simple backing-field implementation as produced by the compiler for an auto-prop, while derived classes can perform additional validation or other logic/calculations.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen about 11 years
    Also a field is a variable and can be passed by reference (ref or out keyword), while a property is a pair of accessors and cannot be passed by reference. For example bool success = TryGetMyTitle(out myBook.Title); which uses out will work with a field and not work with a property. This is a clear example of why the change from field to property is a breaking change!
  • Kyle Baran
    Kyle Baran almost 11 years
    @JeppeStigNielsen: Is there a way to get a property to work with ref and out? That seems like the only advantage variables have over them.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen almost 11 years
    @KyleBaran No, it doesn't make much sense because a property is a pair of accessor methods, not a variable. A usual thing to do is to declare a local variable (possibly read the property an put its value into the local variable), pass the local variable as ref/out, and then set the property to the value the local variable then has. But then the method called does not itself access the property, it accesses the local variable you made there.
  • Jon
    Jon almost 10 years
    Also, to give auto properties a default value, you have to do it in the constructor. At least until C# 6.0, see stackoverflow.com/a/40754/297451
  • Admin
    Admin almost 9 years
    I liked this Answer because it does not use the words 'reflection', 'interface' or 'override'. (too bad about 'contract')
  • the berserker
    the berserker over 7 years
    No one mentioned yet, that readonly is only possible with fields and it's not really the same thing as private set on auto-properties.
  • Michael Stum
    Michael Stum over 7 years
    @theberserker True, although in C# 6 you can do public int Foo { get; } which will create an auto-property with a readonly backing field.
  • the berserker
    the berserker over 7 years
    @michael-stum true. Actually that makes the public int Foo { get; } and public readonly int Foo much better comparison.
  • yu_ominae
    yu_ominae about 7 years
    Also one difference in the IDE is that CodeLens works for properties, but not for fields (in VS2013 at least). I know I shouldn't depend on IDE tools for how I write my code, but that feature alone is why I always use automatic properties instead of fields.
  • Luaan
    Luaan over 4 years
    Ten years later, data breakpoints are here, at least for .NET Core :)
  • Thomas
    Thomas over 3 years
    Also, you can't use fields in interfaces (obviously), but you can use properties, because properties are methods! At least when your code is converted to IL-code. Each accessor in your properties, like the 'get' accessor in property Name, becomes method 'get_Name', 'set_Name' etc. Interfaces may not be where you want your properties, but I must admit I don't get why this hasn't been mentioned yet. interface IProperties { int Age { get; set; } string Name { get; } bool IsMale { set; } }
  • VimNing
    VimNing over 3 years
    Why not just say: encapsulation.
  • VimNing
    VimNing over 3 years
    Why not just say: encapsulation.
  • FailedUnitTest
    FailedUnitTest over 2 years
    @Rainning this is much more clear
  • Thomas Maierhofer
    Thomas Maierhofer over 2 years
    Are you aware that changing a filed to a property breakes the binary contract of the assembly? You can't just xcopy deploy such a new assembly. Everybody has to recompile its code if you go from fields to properties. So it is really a breaking change.
  • Joel Croteau
    Joel Croteau over 2 years
    @ThomasMaierhofer yes, that is my entire first bullet point.
  • Ian W
    Ian W almost 2 years
    To end my newly found hatred of public fields, I need better error messages. In building a SelectList in Razor Pages, I accidentally omitted the auto properties on the class that was the basis for my list of <select> choices. The SelectList constructor happily succeed, but the page rendering result was "Object not set to an instance of an object' in some messy reflection errors. (I'm unwilling to admit how much time that cost me.) At least I now know databinding was the issue...