Что в C # отличает поле от свойства и когда следует использовать поле вместо свойства?
c#
properties
field
аноним
источник
источник
Ответы:
Свойства выставляют поля. Поля должны (почти всегда) быть приватными для класса и доступны через свойства get и set. Свойства обеспечивают уровень абстракции, позволяющий вам изменять поля, не влияя на внешний доступ к ним со стороны вещей, которые используют ваш класс.
@Kent указывает, что свойства не требуются для инкапсуляции полей, они могут выполнять вычисления в других полях или служить другим целям.
@GSS указывает, что вы также можете использовать другую логику, например, проверку доступа к свойству, еще одну полезную функцию.
источник
string
, мой контракт: назначить любые символы до ~ 2bil длины. Если свойство естьDateTime
, мой контракт: назначить любые числа в пределах DateTime, которые я могу посмотреть. Если создатель добавляет ограничения в установщики, эти ограничения не передаются. Но если вместо этого создатель изменяет тип сstring
наSurname
, то его новый класс Фамилия сообщает об ограничениях, и свойствоpublic Surname LastName
не имеет проверки установщика. Кроме того,Surname
является многоразовым.Surname
в моем примере это можно многократно использовать, вам не нужно беспокоиться о дальнейшем копировании / вставке этих проверок в установщике свойств в другие места кода. Не удивительно, если проверка Фамилии происходит в нескольких местах, если вы когда-либо вносите изменения в бизнес-правила для Фамилий. Проверьте ссылку, которую я отправил о Value ObjectsПринципы объектно-ориентированного программирования говорят о том, что внутренняя работа класса должна быть скрыта от внешнего мира. Если вы выставляете поле, вы, по сути, выставляете внутреннюю реализацию класса. Поэтому мы заключаем поля в свойства (или методы в случае Java), чтобы дать нам возможность изменить реализацию, не нарушая код в зависимости от нас. То, как мы можем поместить логику в Свойство, также позволяет нам выполнять логику проверки и т. Д., Если нам это нужно. C # 3 имеет, возможно, запутывающее представление об авто свойствах. Это позволяет нам просто определить свойство, и компилятор C # 3 сгенерирует для нас приватное поле.
источник
public int myVar { get; set; }
самом деле означает (и я предполагаю, что это причина как минимум 50% показов получает этот вопрос).virtual
сами являются частью объектно-ориентированного программирования.virtual
ООП как таковой. Это инструмент, который обеспечивает полиморфизм, который является одним из ключевых инструментов, который включает ООП. Это не ООП само по себе, хотя, и нет ничего по сути ООП в отношении публичного автоприменения. Я бы не стал считать такие вещи, как рефлексия или привязка к ООП, связанные с данными. Обычно я не был бы настолько педантичен в этом, но в ответе конкретно упоминались ОО-принципы как движущая сила примера кода, и я не согласен с этим.Важным отличием является то, что интерфейсы могут иметь свойства, но не поля. Для меня это подчеркивает, что свойства должны использоваться для определения открытого интерфейса класса, в то время как поля предназначены для использования в частной, внутренней работе класса. Как правило, я редко создаю открытые поля и так же редко создаю непубличные свойства.
источник
Я дам вам несколько примеров использования свойств, которые могут привести к вращению шестерен:
источник
Используя Свойства, вы можете вызвать событие, когда значение свойства изменяется (aka. PropertyChangedEvent) или перед изменением значения для поддержки отмены.
Это невозможно с полями (прямой доступ).
источник
Поскольку многие из них объяснили с техническими плюсами и минусами
Properties
иField
, пришло время перейти к примерам в реальном времени.1. Свойства позволяют установить уровень доступа только для чтения.
Рассмотрим случай
dataTable.Rows.Count
иdataTable.Columns[i].Caption
. Они приходят из класса,DataTable
и оба являются для нас публичными. Разница в уровне доступа к ним заключается в том, что мы не можем установить значение,dataTable.Rows.Count
но мы можем читать и писатьdataTable.Columns[i].Caption
. Это возможно черезField
? Нет !!! Это может быть сделаноProperties
только с.2. Свойства в PropertyGrid
Возможно, вы работали
Button
в Visual Studio. Его свойства отображаются в том жеPropertyGrid
духеText
иName
т. Д. Когда мы перетаскиваем кнопку и когда щелкаем свойства, она автоматически находит классButton
и фильтрыProperties
и показывает их вPropertyGrid
(гдеPropertyGrid
не будет отображаться,Field
даже если они общедоступны).В
PropertyGrid
свойствахName
иText
будет показано, но нетSomeProperty
. Почему??? Потому что свойства могут принимать атрибуты . Это не показывает в случае, когда[Browsable(false)]
ложно.3. Может выполнять операторы внутри свойств
4. В Binding Source можно использовать только свойства
Binding Source помогает нам уменьшить количество строк кода.
Fields
не принимаютсяBindingSource
. Мы должны использоватьProperties
для этого.5. Режим отладки
Представьте, что мы используем
Field
для хранения значения. В какой-то момент нам нужно отладить и проверить, где значение становится нулевым для этого поля. Это будет трудно сделать, когда количество строк кода больше 1000. В таких ситуациях мы можем использоватьProperty
и можем установить режим отладки внутриProperty
.источник
ОТЛИЧИЯ - ИСПОЛЬЗОВАНИЕ (когда и почему)
Поле является переменной , которая объявляется непосредственно в классе или структуры. Класс или структура могут иметь поля экземпляра или статические поля или оба. Как правило, вы должны использовать поля только для переменных, которые имеют частную или защищенную доступность . Данные, которые ваш класс предоставляет клиентскому коду, должны предоставляться через методы, свойства и индексаторы. Используя эти конструкции для косвенного доступа к внутренним полям, вы можете защититься от недопустимых входных значений.
Свойство является элементом , который обеспечивает гибкий механизм для чтения, записи или вычислений значения частной области. Свойства можно использовать так, как будто они являются открытыми членами данных, но на самом деле это специальные методы, называемые методами доступа . Это позволяет легко получать доступ к данным, а также способствует безопасности и гибкости методов . Свойства позволяют классу предоставлять открытый способ получения и установки значений, скрывая при этом код реализации или проверки. Метод доступа к свойству get используется для возврата значения свойства, а метод доступа к set используется для назначения нового значения.
источник
Свойства имеют основное преимущество, позволяя вам изменять способ доступа к данным объекта, не нарушая его общедоступный интерфейс. Например, если вам нужно добавить дополнительную проверку или преобразовать сохраненное поле в вычисляемое, вы можете сделать это легко, если вы изначально выставили поле как свойство. Если вы только что выставили поле напрямую, вам придется изменить открытый интерфейс вашего класса, чтобы добавить новые функциональные возможности. Это изменение нарушит работу существующих клиентов и потребует их перекомпиляции, прежде чем они смогут использовать новую версию вашего кода.
Если вы пишете библиотеку классов, предназначенную для широкого потребления (например, .NET Framework, которой пользуются миллионы людей), это может стать проблемой. Однако, если вы пишете класс, используемый внутри небольшой базы кода (скажем, <= 50 тыс. Строк), это на самом деле не имеет большого значения, потому что ваши изменения ни на кого не повлияют. В этом случае все сводится к личным предпочтениям.
источник
Свойства поддерживают асимметричный доступ, т. Е. Вы можете иметь либо геттер и сеттер, либо только один из двух. Точно так же свойства поддерживают индивидуальную доступность для getter / setter. Поля всегда симметричны, то есть вы всегда можете получить и установить значение. Исключением являются поля только для чтения, которые, очевидно, не могут быть установлены после инициализации.
Свойства могут работать очень долго, иметь побочные эффекты и даже создавать исключения. Поля быстрые, без побочных эффектов и никогда не будут генерировать исключения. Из-за побочных эффектов свойство может возвращать различное значение для каждого вызова (как может иметь место в случае DateTime.Now, то есть DateTime.Now не всегда равен DateTime.Now). Поля всегда возвращают одно и то же значение.
Поля могут использоваться для параметров out / ref, свойства - нет. Свойства поддерживают дополнительную логику - это может быть использовано для реализации отложенной загрузки среди прочего.
Свойства поддерживают уровень абстракции, инкапсулируя все, что это означает, чтобы получить / установить значение.
Используйте свойства в большинстве случаев, но старайтесь избегать побочных эффектов.
источник
В фоновом режиме свойство компилируется в методы. Таким образом,
Name
свойство компилируется вget_Name()
иset_Name(string value)
. Вы можете увидеть это, если изучите скомпилированный код. Таким образом, при их использовании возникают (очень) небольшие потери производительности. Обычно вы всегда будете использовать свойство, если вы выставляете поле снаружи, и вы часто будете использовать его внутри, если вам нужно проверить значение.источник
Если вы хотите, чтобы ваша личная переменная (поле) была доступна для объекта вашего класса из других классов, вам нужно создать свойства для этих переменных.
например, если у меня есть переменные с именами «id» и «name», которые являются частными, но может быть ситуация, когда эта переменная необходима для операции чтения / записи вне класса. В этой ситуации свойство может помочь мне получить эту переменную для чтения / записи в зависимости от получения / набора, определенного для свойства. Свойство может быть доступно только для чтения / записи только / чтения.
вот демо
источник
Второй вопрос здесь, «когда следует использовать поле вместо свойства?», Только вкратце затронут в этом другом ответе и вроде как на этом , но не очень подробно.
В общем, все остальные ответы на тему хорошего дизайна: предпочитайте выставлять свойства, а не выставлять поля. Хотя вы, вероятно, не будете регулярно говорить: «Ух ты, представь, насколько хуже будет, если бы я сделал это полем вместо свойства», гораздо реже можно подумать о ситуации, когда ты скажешь «Ух ты, слава богу, я использовал здесь поле вместо собственности ".
Но есть одно преимущество, которое поля имеют над свойствами, и это их способность использоваться в качестве параметров «ref» / «out». Предположим, у вас есть метод со следующей подписью:
и предположим, что вы хотите использовать этот метод для преобразования массива, созданного следующим образом:
Вот я думаю, что самый быстрый способ сделать это, так как X и Y являются свойствами:
И это будет очень хорошо! Если у вас нет измерений, которые доказывают обратное, нет никаких причин вонять. Но я полагаю, что технически не гарантировано, что это будет так быстро:
Выполняя некоторые измерения самостоятельно, версия с полями занимает около 61% времени как версия со свойствами (.NET 4.6, Windows 7, x64, режим выпуска, без отладчика). Чем дороже
TransformPoint
становится метод, тем меньше становится разница. Чтобы повторить это самостоятельно, бегите с закомментированной первой строкой и без закомментированной.Даже если для вышеописанного не было выигрыша в производительности, существуют другие места, где возможность использования параметров ref и out может быть полезной, например, при вызове семейства методов Interlocked или Volatile . Примечание. В случае, если это новость для вас, Volatile - это, по сути, способ добиться того же поведения, которое обеспечивает
volatile
ключевое слово. Таким образом,volatile
он не может волшебным образом решить все проблемы с безопасностью потоков, как его название предполагает, что может.Я определенно не хочу показаться, что я выступаю за то, чтобы вы говорили: «О, я должен начать выставлять поля вместо свойств». Дело в том, что если вам нужно регулярно использовать эти члены в вызовах, которые принимают параметры «ref» или «out», особенно для чего-то, что может быть простым типом значения, которому вряд ли когда-либо понадобится какой-либо из элементов свойств с добавленной стоимостью, аргумент может быть сделан.
источник
Хотя поля и свойства похожи друг на друга, они представляют собой 2 совершенно разных языковых элемента.
Поля являются единственным механизмом хранения данных на уровне класса. Поля являются концептуально переменными в области видимости класса. Если вы хотите сохранить некоторые данные в экземплярах ваших классов (объектов), вам нужно использовать поля. Другого выбора нет. Свойства не могут хранить какие-либо данные, хотя может показаться, что они могут это сделать. Смотрите ниже.
Свойства с другой стороны никогда не хранят данные. Это просто пары методов (get и set), которые можно синтаксически вызывать аналогично полям, и в большинстве случаев они обращаются к (для чтения или записи) полям, что является источником некоторой путаницы. Но поскольку методы свойств являются (с некоторыми ограничениями, такими как фиксированный прототип) обычными методами C #, они могут делать то же, что и обычные методы. Это означает, что они могут иметь 1000 строк кода, они могут генерировать исключения, вызывать другие методы, могут быть даже виртуальными, абстрактными или переопределенными. Особенность свойств заключается в том, что компилятор C # сохраняет некоторые дополнительные метаданные в сборках, которые можно использовать для поиска определенных свойств - широко используемой функции.
Методы получения и установки свойств имеют следующие прототипы.
Таким образом, это означает, что свойства можно «эмулировать», определив поле и 2 соответствующих метода.
Такая эмуляция свойств типична для языков программирования, которые не поддерживают свойства - например, стандартный C ++. В C # там вы всегда должны предпочитать свойства как способ доступа к вашим полям.
Поскольку только поля могут хранить данные, это означает, что чем больше полей содержит класс, тем больше объектов памяти такого класса будет использовать. С другой стороны, добавление новых свойств в класс не делает объекты такого класса больше. Вот пример.
Хотя методы свойств могут делать что угодно, в большинстве случаев они служат способом доступа к полям объектов. Если вы хотите сделать поле доступным для других классов, вы можете сделать это двумя способами.
Вот класс с использованием открытых полей.
Хотя код является абсолютно корректным, с точки зрения дизайна, он имеет несколько недостатков. Поскольку поля могут быть прочитаны и записаны, пользователь не может запретить запись в поля. Вы можете применить
readonly
ключевое слово, но таким образом, вы должны инициализировать поля только для чтения только в конструкторе. Более того, ничто не мешает вам хранить недопустимые значения в ваших полях.Код действителен, все назначения будут выполнены, хотя они нелогичны.
Age
имеет отрицательное значение,YearOfBirth
находится в далеком будущем и не соответствует возрасту иFullName
является нулевым. С полями вы не можете запретить пользователямclass Name
делать такие ошибки.Вот код со свойствами, которые решают эти проблемы.
Обновленная версия класса имеет следующие преимущества.
FullName
иYearOfBirth
проверяются на недопустимые значения.Age
не для записи. Это исчисляется сYearOfBirth
текущего года.FullNameInUppercase
преобразуетсяFullName
в верхний регистр. Это немного надуманный пример использования свойств, где свойства обычно используются для представления значений полей в формате, более подходящем для пользователя - например, с использованием текущей локали на определенном числовомDateTime
формате.Кроме того, свойства могут быть определены как виртуальные или переопределенные - просто потому, что они являются обычными .NET-методами. Для таких методов свойств применяются те же правила, что и для обычных методов.
C # также поддерживает индексаторы, которые являются свойствами, у которых есть параметр индекса в методах свойств. Вот пример.
Начиная с C # 3.0 позволяет определять автоматические свойства. Вот пример.
Несмотря на то, что он
class AutoProps
содержит только свойства (или выглядит так), он может хранить 2 значения, а размер объектов этого класса равенsizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 байт.Причина этого проста. Когда вы определяете автоматическое свойство, компилятор C # генерирует автоматический код, который содержит скрытое поле и свойство с методами свойств, обращающимися к этому скрытому полю. Вот код, который производит компилятор.
Вот код, сгенерированный ILSpy из скомпилированной сборки. Класс содержит сгенерированные скрытые поля и свойства.
Итак, как вы можете видеть, компилятор по-прежнему использует поля для хранения значений - поскольку поля являются единственным способом хранения значений в объектах.
Итак, как вы можете видеть, хотя свойства и поля имеют одинаковый синтаксис использования, они представляют собой совершенно разные понятия. Даже если вы используете автоматические свойства или события - скрытые поля генерируются компилятором, в котором хранятся реальные данные.
Если вам нужно сделать значение поля доступным для внешнего мира (пользователей вашего класса), не используйте открытые или защищенные поля. Поля всегда должны быть помечены как частные. Свойства позволяют вам выполнять проверку значений, форматирование, преобразования и т. Д. И, как правило, делают ваш код более безопасным, более читаемым и расширяемым для будущих изменений.
источник
Кроме того, свойства позволяют использовать логику при установке значений.
Таким образом, вы можете сказать, что хотите установить значение только в целочисленное поле, если значение больше x, в противном случае выдается исключение.
Действительно полезная функция.
источник
Если вы собираетесь использовать потоковые примитивы, вы вынуждены использовать поля. Свойства могут сломать ваш многопоточный код. Кроме того, то, что сказал Кори, правильно.
источник
(Это действительно должен быть комментарий, но я не могу опубликовать комментарий, поэтому, пожалуйста, извините, если он не подходит как сообщение).
Однажды я работал в месте, где рекомендуемой практикой было использование открытых полей вместо свойств, когда эквивалентное свойство def просто обращалось к полю, как в:
Их аргументация заключалась в том, что публичное поле может быть преобразовано в собственность позже в будущем, если потребуется. В то время это казалось мне немного странным. Судя по этим постам, похоже, что не многие здесь согласятся. Что вы могли бы сказать, чтобы попытаться что-то изменить?
Редактировать: я должен добавить, что вся база кода в этом месте была скомпилирована одновременно, поэтому они могли подумать, что изменение открытого интерфейса классов (путем изменения открытого поля для свойства) не было проблемой.
источник
Технически, я не думаю, что есть разница, потому что свойства - это просто обертки вокруг полей, созданных пользователем или автоматически созданных компилятором. Цель свойств - обеспечить инкапсуляцию и предложить облегченную функцию, похожую на метод. Это просто плохая практика объявлять поля как общедоступные, но это не имеет никаких проблем.
источник
Поля - это обычные переменные-члены или экземпляры класса. Свойства - это абстракция для получения и установки своих значений . Свойства также называются средствами доступа, потому что они предлагают способ изменить и извлечь поле, если вы выставите поле в классе как личное. Как правило, вы должны объявить свои переменные-члены частными, а затем объявить или определить свойства для них.
источник
Свойства инкапсулируют поля, что позволяет вам выполнять дополнительную обработку значения, которое нужно установить или получить. Обычно излишне использовать свойства, если вы не будете выполнять предварительную или постобработку значения поля.
источник
IMO, свойства - это просто пары функций / методов / интерфейсов "SetXXX ()" "GetXXX ()", которые мы использовали ранее, но они более лаконичны и элегантны.
источник
Традиционно закрытые поля устанавливаются через методы получения и установки. Ради меньшего количества кода вы можете использовать свойства для установки полей.
источник
когда у вас есть класс, который "Автомобиль". Свойства цвета, формы ..
Где поля - это переменные, определенные в области видимости класса.
источник
Из Википедии - Объектно-ориентированное программирование :
Свойства на самом деле являются частью поведения объекта, но предназначены для того, чтобы предоставить потребителям объекта иллюзию / абстракцию работы с данными объекта.
источник
Мой дизайн поля состоит в том, что поле должно быть изменено только его родителем, следовательно, классом. В результате переменная становится закрытой, чтобы иметь возможность дать право читать классы / методы за ее пределами, я прохожу через систему свойств только с Get. Затем поле извлекается свойством и доступно только для чтения! Если вы хотите изменить его, вы должны пройти через методы (например, конструктор), и я считаю, что благодаря этому способу обеспечения вашей безопасности мы можем лучше контролировать наш код, потому что мы «отбираем». Можно было бы всегда все обнародовать, поэтому каждый возможный случай, понятие переменных / методов / классов и т. Д. ... на мой взгляд, это всего лишь помощь в разработке, поддержке кода. Например, если человек возобновляет код с открытыми полями, он может делать что угодно и, следовательно, что-то «нелогичное» по отношению к цели, логика того, почему код был написан. Это моя точка зрения.
Когда я использую классические модели приватных полей / общедоступных свойств только для чтения, для 10 приватных полей я должен написать 10 публичных свойств! Код может быть действительно большим быстрее. Я обнаружил частный установщик, и теперь я использую только общедоступные свойства с частным установщиком. Сеттер создает в фоновом режиме приватное поле.
Вот почему мой старый классический стиль программирования был:
Мой новый стиль программирования:
источник
Подумайте об этом: у вас есть комната и дверь, чтобы войти в эту комнату. Если вы хотите проверить, как кто входит и обезопасить вашу комнату, то вы должны использовать свойства, иначе они не будут никакой дверью, и каждый легко войдет без каких-либо правил.
Люди попадают в раздел Один довольно легко, не было никакой проверки
Теперь вы проверили человека и знаете, есть ли у него что-то плохое с ним
источник
Поля являются переменными в классах. Поля - это данные, которые вы можете инкапсулировать с помощью модификаторов доступа.
Свойства похожи на поля в том, что они определяют состояния и данные, связанные с объектом.
В отличие от поля свойство имеет специальный синтаксис, который контролирует, как человек читает данные и записывает данные, они известны как операторы get и set. Заданная логика часто может использоваться для проверки.
источник
Свойства - это особый вид члена класса. В свойствах мы используем предопределенный метод Set или Get. Они используют методы доступа, с помощью которых мы можем читать, записывать или изменять значения приватных полей.
Например, давайте возьмем класс с именем
Employee
, с закрытыми полями для имени, возраста и Employee_Id. Мы не можем получить доступ к этим полям извне класса, но мы можем получить доступ к этим частным полям через свойства.Почему мы используем свойства?
Делать поле класса общедоступным и показывать его рискованно, так как вы не будете контролировать, что будет назначено и возвращено.
Чтобы понять это на примере, давайте возьмем класс ученика, у которого есть ID, пароль, имя. Теперь в этом примере некоторые проблемы с открытым полем
Чтобы устранить эту проблему, мы используем метод Get и Set.
Теперь мы возьмем пример метода get и set
источник
Дополнительная информация: По умолчанию методы доступа get и set доступны так же, как и само свойство. Вы можете контролировать / ограничивать доступ к средствам доступа индивидуально (для получения и установки), применяя к ним более ограничивающие модификаторы доступа.
Пример:
Здесь get все еще общедоступен (так как свойство общедоступно), но set защищен (более ограниченный спецификатор доступа).
источник
Свойства используются для выставления поля. Они используют методы доступа (set, get), через которые можно читать, записывать или манипулировать значениями приватных полей.
Свойства не называют места хранения. Вместо этого у них есть средства доступа, которые читают, записывают или вычисляют свои значения.
Используя свойства, мы можем установить проверку типа данных, заданных для поля.
Например, у нас есть частное целое поле возраста, на котором мы должны разрешить положительные значения, так как возраст не может быть отрицательным.
Мы можем сделать это двумя способами, используя getter и setters и используя свойство.
Автоматически реализованное свойство Если мы не используем логику в методах get и set, мы можем использовать автоматически реализованное свойство.
При использовании автоматически реализуемых свойств компиляция создает частное анонимное поле, к которому можно получить доступ только через методы доступа get и set.
Абстрактные свойства Абстрактный класс может иметь абстрактное свойство, которое должно быть реализовано в производном классе
Мы можем приватно установить свойство. В этом мы можем приватно установить свойство auto (устанавливается с помощью класса).
Вы можете достичь того же с помощью этого кода. В этом наборе свойств функция недоступна, так как мы должны установить значение для поля напрямую.
источник
В подавляющем большинстве случаев это будет имя свойства, к которому вы обращаетесь, а не имя переменной ( поле ). Причина этого заключается в том, что он считается хорошей практикой в .NET и в C #, в частности, для защиты каждого фрагмента данных в классе будь то переменная экземпляра или статическая переменная (переменная класса), потому что она связана с классом.
Защитите все эти переменные с соответствующими свойствами, которые позволяют вам определять, устанавливать и получать методы доступа и выполнять такие вещи, как проверка, когда вы манипулируете этими частями данных.
Но в других случаях, таких как класс Math (пространство имен System), в класс встроено несколько статических свойств. одна из которых является математической константой PI
например. Math.PI
и поскольку PI является частью данных, которые четко определены, нам не нужно иметь несколько копий PI, это всегда будет одно и то же значение. Таким образом, статические переменные иногда используются для обмена данными между объектами класса, но они также обычно используются для постоянной информации, когда вам нужна только одна копия фрагмента данных.
источник