В чем преимущества объявления переменной-члена только для чтения? Это просто защита от того, чтобы кто-то изменил его значение в течение жизненного цикла класса, или использование этого ключевого слова приводит к каким-либо улучшениям скорости или эффективности?
295
readonly
поля структурных типов налагают снижение производительности по сравнению с изменяемыми полями, которые просто не видоизменяются, поскольку вызов любого члена поля типаreadonly
значения заставит компилятор сделать копию поля и вызвать член на этом.Ответы:
readonly
Используется ключевое слово , чтобы объявить переменную - член постоянной, но позволяет значение , которое будет вычисленного во время выполнения. Это отличается от константы, объявленной сconst
модификатором, значение которого должно быть установлено во время компиляции. Используяreadonly
вы можете установить значение поля либо в объявлении, либо в конструкторе объекта, членом которого является поле.Также используйте его, если вы не хотите перекомпилировать внешние DLL, которые ссылаются на константу (так как она заменяется во время компиляции).
источник
Я не верю, что использование поля только для чтения дает какой-либо выигрыш в производительности. Это просто проверка, чтобы убедиться, что после того, как объект полностью построен, это поле не может быть указано на новое значение.
Однако «только для чтения» очень отличается от других типов семантики «только для чтения», потому что она применяется CLR во время выполнения. Ключевое слово readonly компилируется в .initonly, что проверяется CLR.
Реальным преимуществом этого ключевого слова является создание неизменных структур данных. Неизменяемые структуры данных по определению не могут быть изменены после создания. Это позволяет очень легко рассуждать о поведении структуры во время выполнения. Например, нет опасности передачи неизменяемой структуры в другую случайную часть кода. Они не могут изменить его никогда, поэтому вы можете надежно программировать против этой структуры.
Вот хорошая запись об одном из преимуществ неизменности: Threading
источник
Нет никаких очевидных преимуществ с точки зрения производительности
readonly
, по крайней мере, ни один из тех, о которых я когда-либо упоминал Это просто для того, чтобы делать то, что вы предлагаете, для предотвращения изменения после его инициализации.Так что это выгодно тем, что помогает вам писать более надежный и читаемый код. Реальная выгода от подобных вещей приходит, когда вы работаете в команде или для технического обслуживания. Объявление чего-либо как
readonly
родственное заключению контракта на использование этой переменной в коде. Думайте об этом как о добавлении документации таким же образом, как и другие ключевые слова, такие какinternal
илиprivate
, вы говорите: «эта переменная не должна изменяться после инициализации», и, более того, вы применяете ее.Таким образом, если вы создаете класс и помечаете некоторые переменные-члены в соответствии
readonly
с дизайном, то вы предотвращаете ошибку себя или другого члена команды позже, когда они расширяют или модифицируют ваш класс. На мой взгляд, это преимущество, которое стоит иметь (за счет небольшой дополнительной языковой сложности, как упоминалось в комментариях).источник
Чтобы выразить это в очень практических условиях:
Если вы используете const в dll A и dll B ссылаются на const, то значение этого const будет скомпилировано в dll B. Если вы переустановите dll A с новым значением для этого const, dll B все равно будет использовать исходное значение.
Если вы используете только для чтения в dll A и dll B ссылки, которые только для чтения, то только для чтения всегда будет просматриваться во время выполнения. Это означает, что если вы повторно внедрите dll A с новым значением для этого только для чтения, dll B будет использовать это новое значение.
источник
const
может иметь выигрыш в производительностиreadonly
. Вот немного более глубокое объяснение с кодом: dotnetperls.com/readonlyreadonly
поля. Вы не можете хранитьnew object();
в a,const
и это имеет смысл, потому что вы не можете запекать не имеющие значения вещи, такие как ссылки на другие сборки, во время компиляции без изменения идентичности.Существует потенциальный случай, когда компилятор может оптимизировать производительность на основе наличия ключевого слова readonly.
Это применимо только в том случае, если поле только для чтения также помечено как статическое . В этом случае JIT-компилятор может предположить, что это статическое поле никогда не изменится. JIT-компилятор может принять это во внимание при компиляции методов класса.
Типичный пример: ваш класс может иметь статическое поле IsDebugLoggingEnabled , предназначенное только для чтения , которое инициализируется в конструкторе (например, на основе файла конфигурации). Как только фактические методы скомпилированы JIT, компилятор может пропустить целые части кода, когда ведение журнала отладки не включено.
Я не проверял, реализована ли эта оптимизация в текущей версии JIT-компилятора, так что это всего лишь предположение.
источник
Имейте в виду, что чтение только относится только к самому значению, поэтому, если вы используете ссылочный тип, только чтение только защищает ссылку от изменения. Состояние экземпляра не защищено только для чтения.
источник
Не забывайте, что есть обходной путь, чтобы получить
readonly
поля, установленные вне любых конструкторов, используяout
params.Немного грязно, но:
Дальнейшее обсуждение здесь: http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx
источник
out
..Удивительно, но чтение только на самом деле может привести к более медленному коду, как обнаружил Джон Скит при тестировании своей библиотеки Noda Time. В этом случае тест, выполненный за 20 секунд, занял всего 4 секунды после удаления только для чтения.
https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/
источник
readonly struct
в C # 7.2, преимущество в том, что поле не читается, исчезает.Если у вас есть предварительно определенное или предварительно рассчитанное значение, которое должно оставаться неизменным во всей программе, тогда вы должны использовать константу, но если у вас есть значение, которое необходимо предоставить во время выполнения, но после присвоения оно должно оставаться неизменным во всей программе, вы должны использовать неизменяемые. например, если вам нужно назначить время запуска программы или вы должны сохранить предоставленное пользователем значение при инициализации объекта, и вам нужно ограничить его от дальнейших изменений, которые вы должны использовать только для чтения.
источник
Добавление базового аспекта для ответа на этот вопрос:
Свойства могут быть выражены как только для чтения, опуская
set
оператора. Поэтому в большинстве случаев вам не нужно добавлятьreadonly
ключевое слово в свойства:В отличие от этого: Полям необходимо
readonly
ключевое слово для достижения аналогичного эффекта:Итак, одно преимущество маркировки поля, которое
readonly
может быть достигнуто, заключается в достижении аналогичного уровня защиты от записи как свойства безset
оператора - без необходимости менять поле на свойство, если по какой-либо причине это желательно.источник
Будьте осторожны с частными массивами только для чтения. Если они представляют клиента как объект (вы можете сделать это для COM-взаимодействия, как я), клиент может манипулировать значениями массива. Используйте метод Clone () при возврате массива в качестве объекта.
источник
ReadOnlyCollection<T>
вместо массива.ImmutableArray<T>
, что позволяет избежать бокса для интерфейса (IReadOnlyList<T>
) или переноса в класс (ReadOnlyCollection
). Он имеет производительность, сравнимую с собственными массивами: blogs.msdn.microsoft.com/dotnet/2013/06/24/…В WPF может быть выигрыш в производительности, поскольку он устраняет необходимость в дорогих свойствах DependencyProperties. Это может быть особенно полезно с коллекциями
источник
Другой интересной частью использования разметки только для чтения может быть защита поля от инициализации в синглтоне.
например в коде из csharpindepth :
readonly играет небольшую роль защиты поля Singleton от повторной инициализации. Другая деталь заключается в том, что для упомянутого сценария вы не можете использовать const, потому что const вызывает создание во время компиляции, а singleton создает во время выполнения.
источник
readonly
можно инициализировать при объявлении или получить его значение только из конструктора. В отличие отconst
него нужно инициализировать и объявить одновременно.readonly
есть всеconst
, плюс инициализация конструкторакод https://repl.it/HvRU/1
источник