public readonly int Foo;
readonly fields can only be set in the constructor, great for immutable types and with much better guarantees than protected/private/no setters.
Reasons for going with a property from the start is if you a) ever use reflection (which would need to change depending on whether the storage is a public field vs a property) b) If you need to implement interfaces using the property. Reasons for going with a public field is for special cases where you know a lot about how inlining affects your performance. Typically in structs.
Since there is no more boilerplate used to write "public int Id { get; }" vs "public readonly int Id", in 99% of cases I'd choose the latter.
The only exception here is for public APIs, but that's a minority of projects.
You mean, change it to a property, then fix dozens or hundreds of references, possibly in downstream dependencies some of which aren't under your control and can't be changed. Sounds fun.
fwiw those are both gross but I've run into both in production code (not written by me, naturally)
If you want to reduce coupling, why not write a real method? Get/Set couples you to your class fields. If you change your class fields, your getters and setters all suddenly become useless.
Maybe I just hate the middle ground (:
I have, plenty of times in the past, changed a class's implementation details in a way that results in fields being removed, without having to create a breaking change in the associated property getters and setters. All it took was changing their implementation to work with whatever the new thing was.
Possibly more importantly, public fields give you no way to create immutable types.