Я не гарантирую, что мой совет будет толковым, но... имхо, требование о приватности полей следует применять умеренно - в первую очередь в классах с нетривиальными методами. Там это позволяет избежать внезапного изменения поля, когда логика работы методов этого не ожидает. В этом случае сеттер свойства может проверить, разрешено ли изменять поле в настоящий момент, и действовать соответственно.
Разумеется, свойства необходимы, если мы планируем использовать паттерн Наблюдатель(Observer), который в C# реализуется через интерфейсы INotifyPropertyChanged и INotifyPropertyChanging. Если вкратце - если мы хотим, чтобы другие объекты могли подписаться на наш объект, и получать уведомления об изменении его состояния. Тут всё понятно - сеттер свойства будет эти уведомления рассылать.
Также свойства могут выручить, если мы потом захотим изменить способ хранения данных, но не захотим изменять "внешний вид" (интерфейс) объекта. Тогда в геттер свойства можно будет поместить код, который пересчитает "внутреннее" представление свойства во "внешнее".
В случае примитивных data transfer objects, как User в твоём примере, я не вижу особенного смысла в использовании свойств ради свойств. Я бы даже сделал его struct, а не class, но это уже пусть спецы по C# меня поправят.
Вообще, любую рекомендацию по проектированию нужно рассматривать не как заповедь, а как некий размен (trade-off): мы выигрываем в X, но проигрываем в Y (зачастую Y = сложность кода). И, соответственно, смотреть, что для тебя важнее.