Свойства против полей: нужна помощь в понимании использования свойств над полями - PullRequest
35 голосов
/ 18 июня 2010

Во-первых, я прочитал список публикаций на эту тему, и я не чувствую, что я понял свойства из-за того, что я понял о инкапсуляции и модификаторах полей (private, public..ect).

Одним из основных аспектов C #, который я изучил, является важность защиты данных в вашем коде с помощью инкапсуляции.Я «думал», что понял, что это из-за способности использовать модификаторы (частные, публичные, внутренние, защищенные).Однако, узнав о свойствах, я в некотором роде разрываюсь с пониманием не только использования свойств, но и общей важности / способности защиты данных (что я понимаю как инкапсуляция) в C #.

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

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

2) они добавляют уровень защиты доступа к данным

Однако из того, что я «подумал», я узнал об использовании модификаторов поля, # 2, мне показалось, что свойства просто генерировали дополнительный код, если у вас не было какой-либо причины для изменения типа (# 1) -потому что вы (более или менее) создаете скрытые методы для доступа к полям, а не напрямую.

Затем можно добавить в свойства целые модификаторы, что еще больше усложняет мое понимание необходимости свойств для доступа к данным.

Я прочитал несколько глав от разных авторов по«Свойства», и ни один из них действительно не объяснил хорошего понимания свойств по сравнению с полями и инкапсуляцией (и хороших методов программирования).

Может кто-нибудь объяснить:

1) , почему я хотел бы использовать свойства вместо полей (особенно когда оно появляется, я просто добавляю дополнительный код

2) любые советы по распознаванию использования свойств ине рассматривает их как простые методы (за исключением get; устанавливает очевидность) при трассировке кода других людей?

3) Какие-либо общие правила, когда дело доходит до хороших методов программированияв связи с тем, когда использовать что?

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

Ответы [ 12 ]

21 голосов
/ 18 июня 2010

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

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

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

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

3) Любые общие правила, когда это приходит к хорошим методам программирования в отношение к тому, когда использовать что?

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

11 голосов
/ 18 июня 2010

Одной из приятных особенностей Properties является то, что геттер и сеттер могут иметь разные уровни доступа.Учтите это:

public class MyClass {

  public string MyString { get; private set; }

  //...other code
}

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

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

9 голосов
/ 18 июня 2010

Вам не нужно беспокоиться о дополнительном коде, необходимом для доступа к полям через свойства, он будет «оптимизирован» компилятором JIT (путем вставки кода).За исключением случаев, когда он слишком велик для встраивания, но в любом случае вам понадобился дополнительный код.

И дополнительный код для определения простых свойств также минимален:

public int MyProp { get; set; } // use auto generated field.

Когда вам нужно настроить вы всегда можете определить свое собственное поле позже.

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

Мойправило: открывать поля всегда через свойства

8 голосов
/ 18 июня 2010
  1. Существует несколько причин, по которым вы можете использовать свойства над полями, вот только пара:

    a.Имея следующее

    public string MyProperty { get; private set; }
    

    , вы делаете свойство «только для чтения».Никто, использующий ваш код, не может изменить его значение.Есть случаи, когда это не совсем верно (если ваша собственность является списком), но они известны и имеют решения.

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

    public string MyProperty
    {
        get { return _myField; }
        set
        {
            if (!string.IsNullOrEmpty(value))
            {
                _myField = value;
            }
        }
    }
    
  2. Вы можете сказать, что это свойства, потому что у них нет ().Компилятор сообщит вам, если вы попытаетесь добавить скобки.

  3. Рекомендуется всегда использовать свойства.

7 голосов
/ 18 июня 2010

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

3 голосов
/ 18 июня 2010

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

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

2 голосов
/ 31 мая 2016

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

private string _name;  
public string Name    
{
   get
     {
       return _name;
     }
   set
     {
      _name = value;
     }
}

Закрытая строка _name используется только классом, тогда как свойство Nameдоступны другим классам в том же пространстве имен.

2 голосов
/ 18 июня 2010

why I would want to use properties instead of fields (especially when it appears I am just adding additional code

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

any tips on recognizing the use of properties and not seeing them as simply methods (with the exception of the get;set being apparent) when tracing other peoples code?

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

Any general rules of thumb when it comes to good programming methods in relation to when to use what?

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

1 голос
/ 18 июня 2010

Одно предостережение заключается в том, что такие вещи, как «Threading.Interlocked.Increment», могут работать с полями, но не могут работать со свойствами. Если два потока одновременно вызывают Threading.Interlocked.Increment для SomeObject.LongIntegerField, значение будет увеличено на два, даже если нет другой блокировки. Напротив, если два потока одновременно вызывают Threading.Interlocked.Increment для SomeObject.LongIntegerProperty, значение этого свойства может быть увеличено на два, или на единицу, или на -4,294,967,295, или кто знает, какие другие значения (свойство может быть записано использовать блокировку, предотвращающую значения, отличные от одного или двух в этом сценарии, но это не могло быть записано, чтобы гарантировать правильное увеличение на два).

1 голос
/ 18 июня 2010

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

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

new foo(){Prop1 = "bar", Prop2 = 33, ...};

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

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

...