C # 3.0 Автоматические свойства, почему бы не получить доступ к полю напрямую?

StackOverflow https://stackoverflow.com/questions/174198

  •  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(...);
    }
}

Это сложная проблема - пытаться создать код, который будет работать в неопределенном будущем.Действительно тяжело.

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

Он сохраняет инкапсуляцию объекта и упрощает чтение кода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top