Вопрос по class, automatic-properties, c#, field, properties – Открытые поля и автоматические свойства

310

Нам часто говорят, что мы должны защищать инкапсуляцию, создавая методы 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 Ringrose
возможный дубликатDifference between Property and Field in C# .NET 3.5+ nawfal
Я склонен делать что-то, что не является частной собственностью, потому что понимание того, что я должен преобразовать поле в собственность, привело к ненужной головной боли.Properties, fields, and methods. Oh My! Вызывает несовместимость, которая укусила меня в прошлом. Steven Wexler

Ваш Ответ

10   ответов
0

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

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

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

158

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

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

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
Также поле являетсяvariable и может быть передано по ссылке (ref или жеout ключевое слово), в то время как свойство является парой методов доступа и не может быть передано по ссылке. Напримерbool success = TryGetMyTitle(out myBook.Title); который используетout будет работать с полем, а не работать со свойством. Это наглядный пример того, почему переход от поля к свойству является серьезным изменением!
@theberserker Правда, хотя в C # 6 вы можете сделатьpublic int Foo { get; } который создаст авто-свойство с полем только для чтения.
& quot; Замена переменной на свойство является критическим изменением. & quot; Это, конечно, применимо только при написании многократно используемой библиотеки, которую большинство разработчиковnot делает.
@KyleBaran Нет, в этом нет особого смысла, потому что свойство - это пара методов доступа, а не переменная. Обычно нужно объявить локальную переменную (возможно, прочитать свойство и поместить его значение в локальную переменную), передать локальную переменную какref/out, а затем установите для свойства значение, которое имеет локальная переменная. Но тогда вызываемый метод сам по себе не обращается к свойству, он обращается к локальной переменной, которую вы там сделали.
Кроме того, свойства, даже авто-свойства, могут быть виртуальными, а поля - нет. Таким образом, базовый класс может иметь простую реализацию вспомогательного поля, созданную компилятором для автоматической поддержки, в то время как производные классы могут выполнять дополнительную проверку или другую логику / вычисления.
61

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

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

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

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

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

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

10

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

0

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

7

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

74

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

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

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

7

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

Похожие вопросы