Подтвердить что ты не робот

Что лучше между модификатором readonly и частным сеттером?

Я работал над созданием класса, и вдруг мне пришла в голову мысль о том, какая разница между двумя кодами:

public readonly string ProductLocation;

и

public string ProductLocation
{
     get;
     private set;
}

Можете ли вы, ребята, дать мне представление, когда лучше использовать следующее. спасибо.

4b9b3361

Ответ 1

Первый - это поле только для чтения, а второе - скомпилировано как пара методов (и все считывания свойства ProductLocation скомпилируются в вызовы к соответствующему методу get, и запись в него получает скомпилированный в вызовы метода set, внутренне эти методы будут читать/записывать во внутреннее, автоматически генерируемое, не читаемое поле). Я бы сказал, что самым важным отличием является безопасность потоков! (как? читать дальше!)

Основное использование класса будет выглядеть точно так же: код в других классах сможет читать только значение, а не изменять его. Кроме того, код для чтения значения будет выглядеть точно так же (например, print(myInstace.ProductLocation); здесь вы не можете сказать, как он был объявлен, прохладно, а?)

Первое, самое тривиальное отличие состоит в том, что свойство с приватным сеттером позволяет экземплярам того же класса изменять значение, тогда как в случае свойства readonly даже сам объект может изменить значение.

Теперь для обеспечения безопасности потоков. Атрибут readonly в этом поле изменит семантику видимости памяти при работе с несколькими потоками (подобно полям Java final).

Поле

A readonly может быть присвоено только объявлению или конструктору. Значение, назначенное для поля readonly, не может быть изменено (по крайней мере, не в обычном режиме), и гарантируется, что каждый поток увидит правильно инициализированное значение после того, как конструктор вернет. Следовательно, поле readonly по сути является потокобезопасным.

Чтобы обеспечить такую ​​же безопасность потоков с помощью этого свойства, вам придется добавить некоторую синхронизацию в свой код, который является подверженным ошибкам. Это может привести к блокировкам, скачкам данных или снижению производительности, в зависимости от случая, и особенно, если вы не испытываете.

Итак, если значение представляет собой то, что семантически не может быть изменено после построения объекта, вы не должны объявлять частный сеттер (это означает, что объект может его изменить). Перейдите для поля readonly (и, возможно, объявите его private и объявите публичное свойство, только получатель получит доступ к полю! Это на самом деле предпочтительная форма, так как нехорошо выставлять поля, лучше всего выставлять методы - там есть много причин, объясняющих, почему в этот ответ)

Ответ 2

Как правило, в .NET не рекомендуется публиковать поля участника публично, они должны быть обернуты свойством. Поэтому предположим, что у вас может быть

private readonly string productLocation; 
public string ProductLocation { get { return productLocation; } } 

vs

public string ProductLocation { get; private set; }

В этой настройке и игнорируя то, что можно было бы выполнить посредством отражения, семантика заключается в том, что в первом случае переменная productLocation может быть инициализирована только на месте и в конструкторе класса. Другие члены класса не могут изменить значение. Внешние потребители не имеют возможности устанавливать значение.

Во второй версии внешние потребители по-прежнему не имеют доступа к установке значения. Однако сам класс может изменить значение в любое время. Если все, что у вас есть, это DTO (то есть класс, который переносит только данные, он не имеет логики, выраженной с помощью методов), то это существенно не все, что отличается от версии readonly. Однако для классов с методами эти методы могут изменить значение productLocation.

Если вы хотите применить концепцию неизменяемого постсооружения поля, используйте readonly. Но для DTO я мог бы воспользоваться опцией private set;, главным образом потому, что это менее шаблонный код.

Ответ 3

Первый (с использованием readonly) будет означать, что объект не может даже изменить собственное значение поля, как только объект был создан, а другие не могут его изменить.

Второй (с использованием private set) будет означать, что объект может изменить значение своего поля после его создания, но другие не могут его изменить.

Я бы использовал первое для чего-то, что, как вы знаете, не изменится, и использовать последнее для чего-то, где значение может измениться, но вы не хотите, чтобы другие его меняли.

Ответ 4

С С# 6.0 инициализатор автоистории существует менее схематичный способ выполнения

private readonly string productLocation; 
public string ProductLocation { get { return productLocation; } } 

Что такое

public string ProductLocation { get; } 

Это только для чтения. Только инициализируется из конструктора или встроенного. После инициализации его нельзя редактировать. (Неизменяемый из любого места)

Однако, если вы используете закрытый набор,

public string ProductLocation { get; private set } 

Это только для чтения извне. Но может быть инициализирован в любое время в любом месте самого класса. И может быть отредактирован в пределах своего жизненного цикла самим классом. (Mutable из класса, неизменяемый снаружи)

Ответ 5

Первое поле , значение которого может быть установлено только при создании экземпляра.

Второй - это свойство , значение которого может быть установлено в любое время (но только с помощью его объекта).


Коррекция: свойство может быть установлено в любой момент любым экземпляром того же класса (и не только его содержащим объектом).