Подтвердить что ты не робот

Зачем использовать поля вместо свойств?

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

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

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

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

4b9b3361

Ответ 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;