В дополнение к ответу @ fretje, приведенному выше, в C # 6 и более поздних версиях теперь реализовано автоматические свойства только для получателя , что позволяет использовать неизменяемые автоматические свойства без необходимости дополнительных явных private readonly
бэк поле. Эквивалентный код будет сокращен до:
class ImmutableType
{
public string Test
{
get; // No Set at all, not even a private set.
}
public ImmutableType(string test)
{
Test = test; // The compiler understands this and initializes the backing field
}
}
Обратите внимание, что private set
(ближайший к неизменяемости может быть получен при использовании автоматических свойств в более ранних версиях C #) только обеспечивает ограниченную инкапсуляцию изменения свойства в том же классе и, следовательно, не является действительно неизменным:
public string Test
{
get;
private set; // Not immutable, since this is still mutable from within the class
}
Подробнее об неизменности
Как уже говорили другие, immutable Property
- это свойство, которое не может измениться после его установки. Установка «единственного значения» обычно выполняется в конструкторе.
immutable Type
- это тип, в котором все (видимые извне) свойства и поля являются неизменяемыми - например, тип «Запись», изначально запланированный для C # 7 (возможно, теперь 8) , был бы неизменный тип. Другие примеры неизменяемых типов: Tuples
и все анонимные классы .
Неизменяемые поля должны быть квалифицированы ключевым словом readonly
в C # - это обеспечивается компилятором, чтобы никакой другой код не пытался изменить поле вне конструктора.
Везде, где это возможно, неизменность полей, переменных и свойств считается хорошей практикой, поскольку это значительно уменьшает площадь поверхности для ошибок (поскольку поля представляют состояние объекта, предотвращение изменения полей уменьшает количество состояний).
Преимущество неизменности особенно важно в многопоточных программах, где два или более потоков одновременно обращаются к одному и тому же объекту. Поскольку несколько одновременных потоков чтения могут безопасно получить доступ к значению поля или свойства, программисту не нужно беспокоиться о проблемах безопасности потоков, связанных с изменением поля другими потоками.
Один общий недостаток неизменности при работе со сложными объектами, состоящими из нескольких составных объектов, заключается в том, что весь граф должен быть построен «за один раз», что может привести к запутанному коду. Распространенным решением здесь является использование шаблона Builder в качестве каркаса, который позволяет создавать переходные, изменяемые представления поэтапно, а затем на последнем этапе .Build()
получается конечный неизменный объект.