readonly - это просто маркер матаданных, которые анализирует компилятор, нужен для того, чтобы обеспечить инкапсуляцию на уровне полей и дать возможность определения значения в конструкторе типа и запретить дальнейшее изменение в коде явным образом (это не значит, что мы не можем изменять такие поля), тоже самое можно сделать и с помощью свойств - закрыв сеттер для изменений вне класса, но если вспомнить историю, то readonly появился раньше свойств, и свойства имеют более широкую область применения, так же поле помеченное readonly можно рассматривать как некую оптимизацию, в сравнении со свойством, т.к. поле будет давать/принимать значение быстрее свойства, за счет того, что свойство преобразуется компилятором в методы get_ и set_, на что тоже уходит время.