Protection from internal representation change is one. Expliciting what can be done with a property is another (i.e force write only or read only properties by only exposing a setter or a getter). Exposing “virtual” properties that are a combination of “real” properties (i.e. exposing a string representation of a price with a currency for instance, where both the price and currency are independant properties). Spying on getters and setters also helps for testing. And so many other potential uses.
Each use case is not a big deal on its own, but there is enough chance to hit at least one of the potential use case for at least some of the objects that autogenerating getter and setters for basically everything is seen as a good practice. Also no one gets fired for putting getter/setters, the reverse could be true.
I personally prefer contexts where I don’t have to care so much about all the above (this means less protective programming in general), but in a lot of enterprisey applications generating getter/setter everywhere is just a way of life.
Certain data types (Array, Java.util.Date) expose private information if you just blindly return your instance variable to the caller. Setting can be dumb, but you may want to create a defensive copy to hand back on get.
C# syntactic sugar makes that apparent to the reader.
However, there are many different types of programming, so I'll concede it the technique could be useful in domains I'm not familiar with. But if there any such situations, then I don't think they explain the wide popularity of getters and setters.
I rarely use getters and setters and it's never been a problem. I also don't use public fields unless the class is only public fields (and the language doesn't have some kind of record/tuple type), as another commenter mentioned.