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

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

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

public class Book
{
    private string _title;

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

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

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

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

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

public class Book
{
    public string Title;
}
 Ian Ringrose01 мар. 2014 г., 17:22
Я преобразовал поле в свойство, чтобы я мог установить точку останова на сеттере
 nawfal03 июн. 2013 г., 18:59
 Steven Wexler16 мая 2014 г., 06:54
Я склонен делать что-то, что не является частной собственностью, потому что понимание того, что я должен преобразовать поле в собственность, привело к ненужной головной боли.Properties, fields, and methods. Oh My! Вызывает несовместимость, которая укусила меня в прошлом.

Ответы на вопрос(10)

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

Решение Вопроса

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

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

Reflection works differently on variables vs. properties, so if you rely on reflection, it's easier to use all properties. You can't databind against a variable.

Changing a variable to a property is a breaking change. For example:

TryGetTitle(out book.Title); // requires a variable
 10 авг. 2016 г., 23:18
@theberserker Правда, хотя в C # 6 вы можете сделатьpublic int Foo { get; } который создаст авто-свойство с полем только для чтения.
 29 дек. 2011 г., 22:29
& quot; Замена переменной на свойство является критическим изменением. & quot; Это, конечно, применимо только при написании многократно используемой библиотеки, которую большинство разработчиковnot делает.
 19 мая 2013 г., 08:31
@KyleBaran Нет, в этом нет особого смысла, потому что свойство - это пара методов доступа, а не переменная. Обычно нужно объявить локальную переменную (возможно, прочитать свойство и поместить его значение в локальную переменную), передать локальную переменную какref/out, а затем установите для свойства значение, которое имеет локальная переменная. Но тогда вызываемый метод сам по себе не обращается к свойству, он обращается к локальной переменной, которую вы там сделали.
 03 мая 2013 г., 11:40
Также поле являетсяvariable и может быть передано по ссылке (ref или жеout ключевое слово), в то время как свойство является парой методов доступа и не может быть передано по ссылке. Напримерbool success = TryGetMyTitle(out myBook.Title); который используетout будет работать с полем, а не работать со свойством. Это наглядный пример того, почему переход от поля к свойству является серьезным изменением!
 07 янв. 2013 г., 19:49
Кроме того, свойства, даже авто-свойства, могут быть виртуальными, а поля - нет. Таким образом, базовый класс может иметь простую реализацию вспомогательного поля, созданную компилятором для автоматической поддержки, в то время как производные классы могут выполнять дополнительную проверку или другую логику / вычисления.

вещь, которую я считаю наиболее ценной при использовании свойства, это отладка.

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

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

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

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

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

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

 28 июл. 2015 г., 19:35
Мне понравился этот ответ, потому что в нем не используются слова «отражение», «интерфейс». или "переопределить". (слишком плохо о «контракте»)

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

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

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

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

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

 21 мар. 2012 г., 09:09
@ zooone9243, + MartinStettner: это было 6 месяцев назад, с тех пор я многому научился. Я забираю это обратно :)
 20 мар. 2012 г., 18:06
@odyodyodys Я согласен с zooone9243: Imp, с точки зрения дизайна, нет никакой разницы между объявлением свойства и объявлением пары получатель / установщик (что является обычной практикой для интерфейсов).
 28 июл. 2011 г., 18:30
Я бы сказал, что если вам нужен интерфейс, который определяет свойства, это должен быть абстрактный класс. Тот факт, что c # позволяет вам определять свойства в интерфейсах, не означает, что вы должны их использовать. Это плохой дизайн.
 04 янв. 2012 г., 16:04
@odyodyodys - я не уверен, что согласен, что это плохой дизайн. Пожалуйста, объясните свое обоснование?

public, Но не забывайте создаватьgetter/setter сprivate Поля нет инкапсуляции. ИМО, если вас не волнуют другие особенностиPropertyВы могли бы также сделать этоpublic.

Ваш ответ на вопрос