406

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;
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
I. J. Kennedy
  • 24,725
  • 16
  • 62
  • 87
  • possible duplicate of [Difference between Property and Field in C# .NET 3.5+](http://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-net-3-5) – nawfal Jun 03 '13 at 16:59
  • 1
    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!](http://www.codeducky.org/properties-fields-and-methods-oh-my/) calls out an incompatibility that has bitten me in the past. – Steven Wexler May 16 '14 at 04:54
  • 4
    The `prop` code snippet makes it fast to create properties. Just type `prop` then tab. – Tono Nam Mar 24 '20 at 22:15

14 Answers14

197

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
    
Community
  • 1
  • 1
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
  • 35
    "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. – Steven Dec 29 '11 at 21:29
  • 37
    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. – KeithS Jan 07 '13 at 18:49
  • 35
    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! – Jeppe Stig Nielsen May 03 '13 at 09:40
  • @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. – Kyle Baran May 19 '13 at 03:13
  • 3
    @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. – Jeppe Stig Nielsen May 19 '13 at 06:31
  • 1
    Also, to give auto properties a default value, you have to do it in the constructor. At least until C# 6.0, see http://stackoverflow.com/a/40754/297451 – Jon Jul 04 '14 at 04:40
  • 2
    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. – the berserker Aug 10 '16 at 21:17
  • 5
    @theberserker True, although in C# 6 you can do `public int Foo { get; }` which will create an auto-property with a readonly backing field. – Michael Stum Aug 10 '16 at 21:18
  • 1
    @michael-stum true. Actually that makes the `public int Foo { get; }` and `public readonly int Foo` much better comparison. – the berserker Aug 11 '16 at 07:51
  • 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. – yu_ominae Feb 21 '17 at 13:05
  • 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; } }` – Thomas Oct 24 '20 at 08:25
93

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.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
80

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.

Rex M
  • 142,167
  • 33
  • 283
  • 313
68

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.

MartinStettner
  • 28,719
  • 15
  • 79
  • 106
57

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.

Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
  • Why not just say: encapsulation. – NeoZoom.lua Oct 31 '20 at 13:39
  • Changing public field to property is not encapsulation. – Danon Jul 21 '22 at 14:10
  • @Danon changing it to a property gives you future ability to add logic in the property, in which case it more clearly becomes encapsulation – Zaid Masud Aug 08 '22 at 14:58
  • @ZaidMasud Not really, it's still coupled to the initial public field value and type. It doesn't give you any protection against data structure change, hence can't be encapsulation. – Danon Aug 08 '22 at 15:01
  • The point is that it may be coupled, but doesn't need to be, and the implementation can change to decouple it later without dependent classes needing to change. The same cannot be said for public member fields. – Zaid Masud Aug 09 '22 at 16:37
13

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.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
11

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.

Arnaldo
  • 141
  • 1
  • 5
10

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.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
8

Trivial properties like these make me sad. They are the worst kind of cargo culting and the hatred for public fields in C# needs to stop. The biggest argument against public fields is future-proofing: If you later decide you need to add extra logic to the getter and setter, then you will have to do a huge refactor in any other code that uses the field. This is certainly true in other languages like C++ and Java where the semantics for calling a getter and setter method are very different from those for setting and getting a field. However, in C#, the semantics for accessing a property are exactly the same as those for accessing a field, so 99% of your code should be completely unaffected by this.

The one example I have seen of changing a field into a property actually being a breaking change at the source level is something like:

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

To this I have to ask, why TF are you passing some other class's field as a reference? Depending on that not being a property seems like the real coding failure here. Assuming that you can directly write to data in another class that you know nothing about is bad practice. Make your own local variable and set book.Title from that. Any code that does something like this deserves to break.

Other arguments I have seen against it:

  • Changing a field to a property breaks binary compatibility and requires any code that uses it to be recompiled: This is a concern iff you are writing code for distribution as a closed-source library. In that case, yes, make sure none of your user-facing classes have public fields and use trivial properties as needed. If however you are like 99% of C# developers and writing code purely for internal consumption within your project, then why is recompilation a big concern? Just about any other change you make is going to require recompilation too, and so what if it does? Last I checked, it is no longer 1995, we have fast computers with fast compilers and incremental linkers, even larger recompilations shouldn't need more than a few minutes, and it has been quite some time since I have been able to use "my code's compiling" as an excuse for swordfighting through the office.
  • You can't databind against a variable: Great, when you need to do that, make it into a property.
  • Properties have features that make them better for debugging like reflection and setting breakpoints: Great, one you need to use one of those things, make it into a property. When you're done debugging and ready to release, if you don't still need those functionalities, change it back into a field.
  • Properties allow you to override behavior in derived classes: Great, if you are making a base class where you think such a scenario is likely, then make the appropriate members into properties. If you're not sure, leave it as a field and you can change it later. Yes, that will probably require some recompilation, but again, so what?

So in summary, yes there are some legitimate uses for trivial properties, but unless you are making a closed source library for public release, fields are easy enough to convert into properties when needed, and an irrational fear of public fields is just some object oriented dogma that we would do well to rid ourselves of.

Joel Croteau
  • 1,682
  • 12
  • 17
  • 1
    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 ` – Ian W May 13 '22 at 16:15
6

For me, the absolute deal breaker for not using public fields was the lack of IntelliSense, showing the references:

enter image description here

Which is not available for fields.

enter image description here

typhon04
  • 2,350
  • 25
  • 22
2

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.

Jinlye
  • 1,774
  • 18
  • 19
1

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.

James Black
  • 41,583
  • 10
  • 86
  • 166
0

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.

TrtlBoy
  • 669
  • 14
  • 17
0

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.

KunYu Tsai
  • 632
  • 1
  • 10
  • 15