C # 3.0 Автоматические свойства, почему бы не получить доступ к полю напрямую?
-
05-07-2019 - |
Вопрос
С новым подходом, заключающимся в том, чтобы получить / установить внутри атрибута класса вот так :
public string FirstName {
get; set;
}
Почему бы просто не сделать атрибут FirstName общедоступным без средства доступа?
Решение
Две большие проблемы с прямым доступом к переменной внутри класса (поле / атрибут):
1) Вы не можете легко привязать данные к полям.
2) Если вы открываете открытые поля из своих классов, вы не сможете позже изменить их на свойства (например: добавить логику проверки в сеттеры)
Другие советы
Потому что в будущем, если вы измените реализацию, код, использующий текущий интерфейс, не сломается.
Например, вы реализуете простой класс с открытым полем и начинаете использовать ваш класс в некоторых внешних модулях. Месяц спустя вы обнаружите, что вам нужно реализовать отложенную загрузку в этом классе. Затем вам нужно будет преобразовать поле в свойство. С точки зрения внешнего модуля, он может выглядеть одинаково синтаксически, но это не так. Свойство - это набор функций, а поле - это смещение в экземпляре класса.
Используя свойство, вы эффективно снижаете риск изменения интерфейса.
Это в основном сводится к тому, что стало общим соглашением о кодировании. Это позволяет легко добавить пользовательский код обработки, если вы хотите. Но вы правы, технически в этом нет реальной необходимости. Однако, если вы добавите пользовательскую обработку позже, это поможет вам не нарушать интерфейс.
Этот стиль записи более полезен, когда вы смешиваете доступность для метода получения и установки. Например, вы можете написать:
public int Foo { get; private set; }
Вы также можете поместить внутренний установщик или даже сделать его закрытым, а установщик общедоступным.
Эта нотация исключает необходимость явной записи закрытой переменной просто для решения классической проблемы значения, доступного для записи / чтения изнутри.
Ключ в том, что компилятор преобразует свойство «под капотом» в пару функций, а когда у вас есть код, который выглядит так, как будто он использует свойство, он фактически вызывает функции при компиляции в IL. Р>
Допустим, вы построили это как поле и имеете код в отдельной сборке, которая использует это поле. Если позже реализация изменится и вы решите сделать это свойством скрывать изменения от остальной части вашего кода, вам все равно придется перекомпилировать и повторно развернуть другую сборку. Если это свойство с самого начала, то все будет просто работать.
Я думаю, что спрашивающий спрашивает, почему бы не сделать следующее ...
public string FirstName { }
Зачем беспокоиться о аксессуарах, если вы можете сократить его до вышеперечисленного. Я думаю, что ответ заключается в том, что требование доступа делает очевидным для человека, читающего код, что это стандартный метод get / set. Без них вы можете видеть выше, трудно заметить, что это автоматически реализуется.
Когда вы получаете сообщение об ошибке и вам нужно выяснить, какие методы изменяют ваши поля и когда, вам будет гораздо важнее. Если поместить легкие аксессоры свойств впереди, это сэкономит феноменальное количество душевной боли, если возникнет ошибка, связанная с областью, которую вы завернули. Я был в такой ситуации пару раз, и это не очень приятно, особенно когда это связано с повторным входом.
Выполнить эту работу заранее и прикрепить точку останова на метод доступа намного проще, чем альтернативы.
В 99% случаев предоставление общедоступного поля - это нормально.
Общий совет заключается в использовании полей:"Если вы предоставляете общедоступные поля из своих классов, вы не сможете позже изменить их на свойства ".Я знаю, что все мы хотим, чтобы наш код был рассчитан на будущее, но с таким мышлением связаны некоторые проблемы:
Потребители вашего класса, вероятно, смогут перекомпилировать его, когда вы измените свой интерфейс.
99% ваших элементов данных никогда не понадобятся для превращения в нетривиальные свойства.Это спекулятивная общность.Вы пишете много кода, который, скорее всего, никогда не будет полезен.
Если вам нужна двоичная совместимость между версиями, внесения элементов данных в свойства, вероятно, недостаточно.По крайней мере, вы должны предоставлять доступ только к интерфейсам и скрывать все конструкторы, а также предоставлять доступ к фабрикам (см. Код ниже).
public class MyClass : IMyClass
{
public static IMyClass New(...)
{
return new MyClass(...);
}
}
Это сложная проблема - пытаться создать код, который будет работать в неопределенном будущем.Действительно тяжело.
У кого-нибудь есть пример того случая, когда использование тривиальных свойств спасло их бекон?
Он сохраняет инкапсуляцию объекта и упрощает чтение кода.