Открытые поля и автоматические свойства

Нам часто говорят, что мы должны защищать инкапсуляцию, создавая методы getter и setter (свойства в С#) для полей класса, вместо того, чтобы подвергать поля внешнему миру.

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

public class Book
{
    private string _title;

    public string Title
    {
          get{ return _title;  }
          set{ _title = value; }
    }
}

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

Затем идет С# 3.0, и я вижу, что они добавили автоматические свойства:

public class Book
{
    public string Title {get; set;} 
}

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

public class Book
{
    public string Title;
}

Ответы

Ответ 1

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

Свойства против общедоступных переменных

  • Отражение работает по-разному по переменным и свойствам, поэтому, если вы полагаетесь на отражение, проще использовать все свойства.
  • Вы не можете привязывать данные к переменной.
  • Изменение переменной в качестве свойства является нарушением. Например:

    TryGetTitle(out book.Title); // requires a variable
    

Ответ 2

Игнорирование проблем API, то, что я считаю наиболее ценным в использовании свойства, - это отладка.

Отладчик CLR не поддерживает точки прерывания данных (большинство отладочных отладчиков). Следовательно, невозможно установить точку останова при чтении или записи определенного поля в классе. Это очень важно для некоторых сценариев отладки.

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

Ответ 3

Переход из поля в свойство нарушает контракт (например, требуется перекомпилировать весь ссылочный код). Поэтому, когда у вас есть точка взаимодействия с другими классами - любой публичный (и вообще защищенный) член, вы хотите планировать будущее развитие. Сделайте это, всегда используя свойства.

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

Ответ 7

Все о стабильности версий и API. Нет никакой разницы в версии 1, но позже, если вы решите, что вам нужно сделать это свойство с некоторой проверкой ошибок в версии 2, вам не нужно менять API-интерфейс без изменений кода в любом месте, кроме определение свойства.

Ответ 8

Нет ничего плохого в создании поля public. Но помните, что создание getter/setter с private не является инкапсуляцией. IMO, Если вам не нужны другие функции Property, вы также можете сделать это public.

Ответ 9

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

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

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

Ответ 10

Одна вещь, которую я нахожу очень полезной, а также все причины кода и тестирования, заключается в том, что если это свойство и поле, то это означает, что среда Visual Studio IDE показывает вам ссылки на свойство, но не поле.

Ответ 11

Одним из аспектов является также производительность. Я обнаружил интересную вещь - в отладочной версии доступ к свойству почти удваивается медленнее (если не больше), чем в поле, НО в версии выпуска доступ к свойству незначительно быстрее, чем в поле!