Зачем когда-либо использовать поля вместо свойств? - PullRequest
36 голосов
/ 30 января 2010

Я довольно новичок в C #, и я думаю, что свойства - замечательная вещь. На самом деле, так замечательно, что я не вижу никакого реального преимущества в использовании полей. Даже для частных полей кажется, что гибкость и модульность, которые предлагают свойства, могут в лучшем случае избавить вас от серьезных головных болей, а в худшем - вообще не дают никакого эффекта.

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

Изменить: Некоторые люди подняли вопрос о необходимости резервного копирования свойств с полями (явно или автоматически). Позвольте уточнить мой вопрос: есть ли причина использовать поля кроме как для резервного копирования свойств ? Т.е., есть ли время, когда SomeType someField; предпочтительнее SomeType SomeProperty { get; set; }?

Edit 2: DanM, Skurmedel и Seth дали действительно полезные ответы. Я принял DanM, поскольку он является наиболее полным, но если бы кто-то суммировал свои ответы в одном ответе, я был бы рад принять его.

Ответы [ 13 ]

25 голосов
/ 30 января 2010

Как правило, свойства нуждаются в вспомогательном поле, если они не являются простыми "автоматическими свойствами" получения / установки.

Итак, если вы просто делаете ...

public string Name { get; set; } // automatic property

... вам не нужно поле, и я согласен, нет причин его иметь.

Однако, если вы делаете ...

public string Name
{
    get { return _name; }
    set 
    {
       if (value = _name) return;
       _name = value;
       OnPropertyChange("Name");
    }
}

... вам нужно это _name вспомогательное поле.

Для закрытых переменных, которые не требуют специальной логики get / set, на самом деле это суждение о том, нужно ли создавать частное автоматическое свойство или просто поле. Я обычно делаю поле, затем, если мне нужно, чтобы оно было protected или public, я изменю его на автоматическое свойство.

Обновление

Как отметил Ясир, если вы используете автоматические свойства, за кулисами все еще скрывается поле, просто вам не нужно ничего печатать. Итак, суть в том, что свойства не хранят данные, они предоставляют доступ к данным. Поля - это то, что на самом деле содержит данные. Так что они вам нужны, даже если вы их не видите.

Обновление 2

Относительно вашего исправленного вопроса ...

есть ли время, когда SomeType someField; предпочтительнее SomeType SomeProperty { get; set; }?

... одна вещь, которая приходит на ум: если у вас есть личное поле, и (в соответствии с соглашением для частных полей) вы называете его _name, это сигнализирует вам и всем, кто читает ваш код, что вы работаете напрямую с личными данными. Если, с другой стороны, вы делаете все свойством и (в соответствии с соглашением о свойствах) вызываете свое частное свойство Name, теперь вы не можете просто посмотреть на переменную и сказать, что это частные данные. Таким образом, использование только свойств удаляет некоторую информацию. Я не пробовал работать со всеми свойствами, чтобы определить, является ли это важной информацией, но что-то определенно потеряно.

Еще одна вещь, более незначительная, заключается в том, что public string Name { get; set; } требует большего набора текста (и немного более грязно), чем private string _name.

12 голосов
/ 30 января 2010

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

Предотвращение чрезмерного использования методов получения и установки свойств

Большинство людей не осознают, что методы получения и установки свойств похожи на методы, когда речь идет о накладных расходах; это в основном синтаксис, который отличает их. Компилятор вставляет не виртуальный метод получения или установки свойств, который не содержит никаких инструкций, кроме доступа к полю, но во многих других случаях это невозможно. Вы должны тщательно продумать ваше использование свойств; Изнутри класса обращайтесь к полям напрямую (если возможно) и никогда не вызывайте свойства вслепую повторно без сохранения значения в переменной. Все это говорит о том, что вы не должны использовать открытые поля!

Источник: http://dotnet.sys -con.com / node / 46342

11 голосов
/ 01 апреля 2010

Просто попробуйте использовать свойство при использовании аргументов ref / out:

someObject.SomeMethod(ref otherObject.SomeProperty);

Не скомпилируется.

10 голосов
/ 30 января 2010

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

Я делаю это довольно часто.

Придуманный пример:

class Rectangle
{
   private readonly int _width;
   private readonly int _height;

   public Rectangle(int width, int height)
   {
      _width = width;
      _height = height;
   }

   public int Width { get { return _width; } }
   public int Height { get { return _height; } }
}

Это означает, что ничто внутри Rectangle не может изменить ширину или высоту после построения. Если кто-то попытается, компилятор будет жаловаться.

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

Еще одна причина, которую я вижу, заключается в том, что если часть данных не должна быть открыта (оставайтесь private), зачем делать это свойством?

5 голосов
/ 30 января 2010

Хотя я согласен с тем, что я воспринимаю как «намерение» в заявлении Дэвида Басараба: «Нет причин публично выставлять поля», я хотел бы добавить немного другой акцент:

Я бы изменил приведенную выше цитату из Дэвида следующим образом: «Нет причин публично выставлять поля ... вне класса ... кроме как через сознательный выбор инкапсуляции полей в свойствах, через которые строго контролируется доступ .

Свойства - это не просто «оболочка» синтаксиса над полями, привязанная к «C #»: они являются фундаментальной функцией языка, разработанной по уважительным причинам, включая:

  1. управление тем, что выставлено и не выставлено вне классов (инкапсуляция, сокрытие данных)

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

  3. Интерфейсы по дизайну не могут определять поля: но могут определять свойства.

Хороший ОО-дизайн означает сознательный выбор «состояния»:

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

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

  3. поля статического экземпляра: какое состояние будет свойством только класса, независимо от количества экземпляров класса.

  4. заявляют, что сознательно и сознательно подвергаются «за пределами» класса: ключевая идея заключается в том, что между классом и «потребителями» данных, предоставляемых классом, имеется по крайней мере один уровень косвенности «Обратная сторона» «экспозиции» - это, конечно, сознательное намерение скрыть (инкапсулировать, изолировать) код реализации.

    а. через общедоступные свойства: все аспекты этого хорошо освещены во всех других ответах здесь

    б. через индексаторы

    с. с помощью методов

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

Предлагаем вам обзор: MSDN для полей ' ... MSDN для свойств ... MSDN для индексаторов

4 голосов
/ 30 января 2010

Я не понимаю, почему вы используете частные автопринадлежности. Какое преимущество есть

private int Count {get; set;}

над

private int count
3 голосов
/ 30 января 2010

Синтаксис для полей записывается намного быстрее, чем для свойств, поэтому, когда безопасно использовать поле (личное для класса), почему бы не использовать его и не сохранить эту дополнительную типизацию? Если автоматически реализованные свойства имеют приятный короткий лаконичный синтаксис, и вам нужно проделать дополнительную работу для создания простого старого поля, люди могут просто начать использовать свойства вместо этого. Кроме того, теперь это соглашение в C #. Так думают люди, и это то, что они ожидают увидеть в коде. Если вы сделаете что-то отличное от обычного, вы запутаете всех.

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

Существует очень простая причина, почему нам все еще нужно иметь явные поля:

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

Я также подозреваю, что это влияет на производительность, но, возможно, это можно решить с помощью дрожания.

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

3 голосов
/ 30 января 2010

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

Вы не всегда видите поля. С автоматическими свойствами C # 3 поле создается для вас компилятором. Но это все еще там. Кроме того, автоматические свойства имеют некоторые существенные ограничения (например, нет поддержки INotifyPropertyChanged, нет бизнес-логики в установщиках), которые означают, что они часто неуместны, и вам все равно нужно создать явное поле и свойство, определенное вручную.

Согласно ответу Дэвида , вы правы, если говорите об API: вы почти никогда не хотите делать внутреннее состояние (поля) частью API.

3 голосов
/ 30 января 2010

Существует нет причин для публичного показа полей.

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

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

2 голосов
/ 30 января 2010

Как уже отмечали другие, вам все равно понадобится личное поле для поддержки свойств.

Также есть преимущество в скорости при использовании полей над свойствами. В 99,99% случаев это не имеет значения. Но в некоторых это может.

...