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


нам часто говорят, что мы должны защищать инкапсуляцию, создавая методы 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;
}
10 295

10 ответов:

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

свойства против открытых переменных

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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