Зачем использовать поля вместо свойств?
Я новичок в С#, и я думаю, что это замечательная вещь. Настолько замечательно, что я не вижу реального преимущества использования полей. Даже для частных полей, похоже, гибкость и модульность, которые предлагают предложения, в лучшем случае избавят вас от серьезных головных болей и в худшем случае не будут иметь никакого эффекта.
Единственное преимущество, которое я могу видеть для полей, заключается в том, что вы можете инициализировать их inline. Но в большинстве случаев вы хотите инициализировать их в конструкторе. Если вы не используете встроенную инициализацию, есть ли причина постоянно не использовать свойства?
Изменить: некоторые люди объясняют необходимость создания резервных копий свойств с помощью полей (явно или автоматически). Позвольте уточнить мой вопрос: есть ли причина использовать поля, кроме резервных свойств? I.e., есть ли когда-либо SomeType someField;
предпочтительнее SomeType SomeProperty { get; set; }
?
Отредактируйте 2: DanM, Skurmedel и Seth все дали действительно полезные ответы. Я принимал DanM, так как он является самым полным, но если кто-то должен был обобщить свои ответы на один ответ, я был бы рад принять его.
Ответы
Ответ 1
Как правило, свойствам требуется поле поддержки, если только они не являются "автоматическими свойствами" getter/setter.
Итак, если вы просто делаете...
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
.
Ответ 2
Свойства - замечательная вещь, но накладные расходы связаны с доступом к ресурсам. Не обязательно проблема, а что-то, о чем нужно знать.
Предотвращение чрезмерного использования свойств Getters and Setters
Большинство людей не понимают, что свойства getters и seters похожи на методы, когда дело доходит до накладных расходов; это в основном синтаксис, который их отличает. Компилятор не привязывает неинтеллектуальный getter или setter, который не содержит инструкций, отличных от доступа к полю, но во многих других случаях это невозможно. Вы должны внимательно рассмотреть свое использование свойств; изнутри класса, поля доступа напрямую (если возможно) и никогда не слепо вызовите свойства повторно, не сохраняя значение в переменной. Все, что сказано, это не означает, что вы должны использовать публичные поля!
Источник: http://dotnet.sys-con.com/node/46342
Ответ 3
Если вы хотите иметь что-то 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
), почему она является свойством?
Ответ 4
Попробуйте использовать свойство при использовании ref/out args:
someObject.SomeMethod(ref otherObject.SomeProperty);
Он не будет компилироваться.
Ответ 5
Я не понимаю, почему вы используете частные автопрограммы. Какое преимущество существует
private int Count {get; set;}
над
private int count
Ответ 6
Существует причина нет публиковать поля.
Если вы публично открываете поле, вы не можете изменить источник информации, от встроенного дефинирования до файла конфигурации без рефакторинга. \
Вы можете использовать поле для скрытия внутренних данных. Я редко пользуюсь этим, я использую только поля, когда я делаю что-то, чтобы скрыть публично и использовать его в собственности. (т.е. я не использую автоматическое генерирование свойств)
Ответ 7
Поля - это единственное место, где вы можете сохранить состояние. Свойства - это всего лишь пара методов со специальным синтаксисом, который позволяет их сопоставлять с методом get или set в зависимости от того, как они используются: если свойство изменяет или получает доступ к состоянию, это состояние все еще должно храниться в поле.
Вы не всегда видите поля. С автоматическими свойствами С# 3 поле создается для вас компилятором. Но он все еще там. Кроме того, автоматические свойства имеют некоторые существенные ограничения (например, поддержка INotifyPropertyChanged, отсутствие бизнес-логики в сеттерах), что означает, что они часто неприемлемы, и вам все равно необходимо создать явное поле и определенное вручную свойство.
Согласно ответ Дэвида, вы правы, если вы говорите об API: вы почти никогда не хотите, чтобы внутреннее состояние (поля) было частью API.
Ответ 8
Синтаксис для полей намного быстрее писать, чем для свойств, поэтому, когда он безопасен для использования поля (закрытого для класса), почему бы не использовать его и не сохранить лишний ввод? Если автоматически реализованные свойства имели красивый короткий сжатый синтаксис, и вам приходилось выполнять дополнительную работу, чтобы создать обычное старое поле, люди могли бы просто начать использовать свойства. Кроме того, это соглашение теперь в С#. Это то, как люди думают, и это то, что они ожидают увидеть в коде. Если вы делаете что-то другое в обычном порядке, вы будете путать всех.
Но вы могли бы спросить, почему синтаксис для полей не создает автоматически реализованное свойство вместо поля, поэтому вы получаете лучшее из обоих миров - свойства везде и краткий синтаксис.
Есть очень простая причина, по которой нам все еще нужно иметь явные поля:
У С# 1.0 не было всех этих приятных функций, которые у нас есть сейчас, поэтому поля были фактом жизни - вы не могли жить без них. Много и много кода полагаются на поля и свойства, представляющие собой разные вещи. Теперь это просто невозможно изменить, не разбивая тонны кода.
Я подозреваю также, что есть последствия для производительности, но, возможно, это может быть решено джиттером.
Итак, мы застряли с полями навсегда, и поскольку они там, и они взяли лучший синтаксис, имеет смысл использовать их, когда это безопасно.
Ответ 9
Хотя я согласен с тем, что я воспринимаю как "намерение" в заявлении Дэвида Басараба: "Нет причин публично раскрывать поля", я хотел бы добавить немного другой акцент:
Я бы изменил цитату из Дэвида выше, чтобы прочитать: "Нет причин публично раскрывать поля... вне класса... за исключением сознательного выбора инкапсуляции полей в свойствах, через которые доступ строго контролируется.
Свойства - это не просто "шпон" синтаксиса над полями, "привязанный к" С#: они являются основной языковой функцией, разработанной по уважительным причинам, включая:
-
контроль над тем, что подвергается и не подвергается внешним классам (инкапсуляция, скрытие данных)
-
позволяет выполнять определенные действия при доступе или задании свойства: действия, которые лучше всего выражаются в свойствах "get" и "set", а не "повышены" к внешним методам.
-
Интерфейсы по дизайну не могут определять поля: но могут определять свойства.
Good OO Design означает создание сознательного выбора "состояние":
-
локальные поля переменных: какое состояние является приватным для метода и переходного процесса: локальные переменные, как правило, действительны только в пределах области метода или даже с "узким сроком службы", как в пределах области чего-то вроде 'для цикла. Конечно, вы можете рассматривать переменные параметра в методе как "локальные".
-
поля экземпляра класса: какое состояние является приватным для класса и имеет независимое существование для каждого экземпляра класса, но, скорее всего, оно должно использоваться в нескольких местах в классе.
-
статические поля экземпляра: какое состояние будет свойством только класса, независимо от количества экземпляров класса.
-
государство сознательно и сознательно раскрывает "вне" класс: ключевая идея заключается в том, что между классом и "потребителями" данных, предоставляемых классом, существует по крайней мере один уровень косвенности. "Отражающая сторона" "экспозиции" - это, конечно, сознательное намерение скрывать (инкапсулировать, изолировать) код реализации.
а. через публичные свойства: все аспекты этого хорошо освещены во всех других ответах здесь.
б. через индексаторы
с. с помощью методов
д. общедоступные статические переменные обычно встречаются в классах служебных программ, которые часто являются статическими классами.
Предложите вам ознакомиться с MSDN на 'Полях... MSDN по свойствам... MSDN on Indexers
Ответ 10
Поля и свойства не являются взаимозаменяемыми. Я предполагаю, что вы говорите, это доступ к частным полям через частные свойства. Я делаю это, когда это имеет смысл, но по большей части это не обязательно. В любом случае оптимизатор JIT будет использовать доступ к частному полю через частную собственность в большинстве случаев. И закрытие частного поля в частной собственности не считается изменением, так как частные члены не являются частью вашего интерфейса.
Лично я никогда не буду раскрывать поля защищенного/публичного экземпляра. Это общеприемлемо, однако, чтобы открыть публичное статическое поле с модификатором readonly, если тип поля сам по себе является неизменным. Это часто наблюдается с staticStart.Empty static fields.
Ответ 11
Как отмечали другие, в любом случае вам понадобится личное поле поддержки для свойств.
Также есть преимущество в использовании полей над свойствами. В 99,99% случаев это не имеет значения. Но в некоторых это может быть.
Ответ 12
Скорость. Если поле устанавливается или читается миллиардами раз в ходе моделирования, вы хотите использовать поле, а не свойство, чтобы избежать накладных расходов на подпрограмму. В соответствии с OO (DDD?), Насколько это возможно, в этих случаях я бы рекомендовал использовать поля только в классе, предназначенном для представления своего рода "ценности", подобного человеку. Логика должна быть сведена к минимуму. Скорее, у вас есть лицо или владелец.
Но если у вас есть эти проблемы, вы, вероятно, не программируете С++, а не С#, не так ли?
Ответ 13
Есть несколько хороших (частичных) ответов от @Seth (поля работают лучше, поэтому в частном контексте вы можете использовать это в свою пользу, когда это имеет смысл), @Skurmedel (поля могут быть только для чтения), @Jenk (поля могут использоваться для ref/out). Но я хотел бы добавить еще одно:
Вы можете использовать упрощенный синтаксис инициализации для установки значения поля, но не свойства. то есть:.
private int x = 7;
против
private int x { get; set; }
// This must go in the constructor, sometimes forcing you to create
// a constructor that has no other purpose.
x = 7;