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

Почему свойства не могут быть прочитаны только?

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

Например:

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; }

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Компилятор даже ссылается на них как "только на чтение", если вы попытаетесь написать им.

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

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

Ответ 3

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

public bool Property {get; private set;}

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

Ответ 4

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

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

string _name;
public string Name
{
     get{ return _name; }
}