Почему свойства не могут быть только для чтения? - PullRequest
32 голосов
/ 30 января 2010

Этот вопрос возник в комментариях к этому ответу . Невозможность иметь свойства только для чтения была предложена в качестве потенциальной причины для использования полей вместо свойств.

Например:

class Rectangle
{
   private readonly int _width;
   private readonly int _height;

   public Rectangle(int width, int height)
   {
      _width = width;
      _height = height;
   }

   public int Width { get { return _width; } }
   public int Height { get { return _height; } }
}

Но почему ты не можешь просто сделать это?

public int Width { get; readonly set; }

Редактировать (уточнение) : Вы можете реализовать эту функцию в первом примере. Но почему вы не можете использовать автоматически реализованное свойство, чтобы сделать то же самое? Это также было бы менее беспорядочным, так как вам не пришлось бы иметь прямой доступ к полям в вашем конструкторе; весь доступ будет через собственность.

Редактировать (обновить) : Начиная с C # 6.0, свойства только для чтения поддерживаются! object MyProp { get; } Это свойство можно установить встроенным (object MyProp { get; } = ...) или в конструкторе, но нигде больше (так же, как readonly поля).

Ответы [ 7 ]

23 голосов
/ 30 января 2010

Потому что язык этого не позволяет.

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

Но функции не предоставляются бесплатно. (Эрик Ганнерсон выражает это как «Каждая функция начинается с минус 100 баллов .») Для реализации автоматических свойств, доступных только для чтения, потребовались бы дополнительные усилия компилятора для поддержки модификатора readonly для свойства (в настоящее время он применяется только к fields), чтобы сгенерировать соответствующее вспомогательное поле и преобразовать sets свойства в присвоения вспомогательному полю. Это довольно трудоемкая работа для поддержки того, что пользователь мог бы сделать достаточно легко, объявив поле для чтения только для чтения и записав однострочное средство получения свойств, и эта работа обойдется в невыполнение других функций.

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

16 голосов
/ 30 января 2010

Если вы хотите сделать свойство «только для чтения» в том, что касается функциональности, вы делаете это только путем предоставления метода get, как вы указали в своем сообщении.

public int Width { get { return _width; } } 
public int Height { get { return _height; } } 

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

Наличие дополнительного условия readonly для свойства будет конфликтовать с предоставлением метода set. Мне кажется, это плохой синтаксис, то есть как человек, читающий его (или, если на то пошло, компилятор), знает, что имеет приоритет: readonly или set?

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

9 голосов
/ 30 января 2010

Вы можете сделать автоматическое свойство только для чтения, указав для него модификатор личного доступа, например так:

public bool Property {get; private set;}

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

2 голосов
/ 30 января 2010

Свойства могут быть только для чтения, но не автоматическими свойствами.

Оба параметра get и set необходимы для автоматических свойств, и для свойства, доступного только для чтения, не имеет смысла иметь значение set.

Вы можете определить обычное свойство как свойство только для чтения, просто указав get - однако, даже если требования для get и set для автоматических свойств не существовали -Свойство только для чтения не может быть определено автоматически, потому что вы должны знать вспомогательное поле, чтобы иметь возможность устанавливать его значение внутренне (т. е. через конструктор).

Полагаю, здесь может быть шаблон / макрос или что-то ещеопределено в VS, чтобы сгенерировать этот код, но он не может быть частью самого языка.

1 голос
/ 30 января 2010

Я думаю, что в основном проблема в том, что свойства являются просто синтаксическим сахаром для поля с дополнительными методами получения / установки. Автоматические свойства генерируют поле поддержки, поэтому им требуется «установщик», иначе не будет возможности установить значение поля поддержки. Поскольку свойства действительно отображаются на методы, а не на поля, нет смысла делать их readonly .

Даже если разрешено, только для чтения может применяться только к автоматическим свойствам. Для традиционных свойств вы можете поместить произвольный код как в получатель, так и в установщик. Даже если установщик мог быть вызван только в конструкторе класса, он все равно может изменить значение на основе любой логики, которую вы решили в него вставить. Это полностью несовместимо с концепцией readonly , что потребует различных правил синтаксиса и поддержки автоматических / традиционных свойств. Поскольку существует механизм - использование традиционных свойств только с определенным геттером И доступным только для чтения полем, как в указанном вопросе - я не вижу смысла портить синтаксис свойства и потенциально вводить в заблуждение что-то с довольно простой и простой реализацией используя текущие языковые конструкции.

0 голосов
/ 11 октября 2018

В C # 6, авто свойства могут быть только для чтения https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-6#read-only-auto-properties

0 голосов
/ 30 января 2010

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

string _name;
public string Name
{
     get{ return _name; }
     private set { _name = value; }
}

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

string _name;
public string Name
{
     get{ return _name; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...