Яка різниця між властивістю та змінною


78

У мене плутанина щодо розуміння властивості та змінних

public class ABC()
{
    public int A;
    public int B { get; set; }
}

Яка точна різниця між A та B?


15
FYI Aзазвичай називають полем, а не змінною.
Брайан Расмуссен




Відповіді:


71

Як багато хто зазначав, A - це поле , B - це властивість .

Справжнє питання полягає в тому, чому ви повинні дбати і що використовувати?

Я посилаюся на допис у блозі Джонатана Анехи :

(Це у VB, але це стосується і C #;))

То навіщо використовувати властивості над полями, 5 причин:

1. Поля не можна використовувати в інтерфейсах

Ви не можете забезпечити існування поля в державному договорі об’єкта через інтерфейс. Що стосується властивостей, це добре працює.

2. Перевірка

Хоча в даний час ваша програма може не вимагати жодної логіки перевірки для встановлення певного значення, зміна бізнес-вимог може вимагати вставки цієї логіки пізніше. На той момент зміна поля на властивість є надзвичайною зміною для споживачів вашого API. (Наприклад, якщо хтось перевіряв ваш клас за допомогою роздумів).

3. Бінарна серіалізація

Зміна поля на властивість є значною зміною, якщо ви використовуєте двійкову серіалізацію. Між іншим, це одна з причин, чому властивості VB10, що реалізуються автоматично, мають поле, яке можна прив'язувати (тобто ви можете висловити ім'я поля резервного копіювання в коді) - таким чином, якщо ви зміните властивість, що реалізується автоматично, на розширену властивість , Ви все ще можете підтримувати сумісність із серіалізацією, залишаючи ім'я поля резервного копіювання однаковим (у C # ви змушені змінити його, оскільки воно генерує поля резервного копіювання з незмінними іменами).

4. Багато інфраструктури прив'язки даних .NET прив'язується до властивостей, але не до полів

Я чув аргументи з обох сторін щодо того, чи це добре, чи ні, але реальність така, як це працює зараз. (Примітка від мене: прив’язки WPF працюють над властивостями)

5. Викриття публічного поля є порушенням FxCop

З багатьох причин, перерахованих вище :)

Причин може бути більше.

Я також хотів би вказати на допис у блозі Джеффа Етвуда та закінчити цитатою з нього:

Дійсно важливо забрати тут - уникати написання коду, який не має значення. І оболонки властивостей навколо загальнодоступних змінних - це сама суть безглуздого коду.


1
І все ж властивості, що реалізуються автоматично, не можуть бути використані як вихідний параметр: / yay c # нав'язує нам безглуздий код
Асимілятор

Оновлена ​​документація для елемента 5 - CA1051: Не оголошувати видимі поля екземпляра docs.microsoft.com/en-us/visualstudio/code-quality/…
Тіаго Крізанто

23

А - поле, В - властивість. Властивість - це в основному синтаксичний цукор для геттерів та сетерів. Визначений вами клас буде скомпільований приблизно так:

public class ABC()
{
    public int A;

    private int backing_B;

    public void set_B(int value)
    {
        backing_B = value;
    }

    public int get_B()
    {
        return backing_B;
    }
}

Зауважте, що цей тип перетворення справедливий для всіх властивостей C # - доступ до ABC.B буде перетворений у виклики методів. Властивості в основному створюють ілюзію "змінної", а насправді є просто хитро замаскованою парою методів.

Це важливо, оскільки це дозволяє вам оголосити власне тіло методу get і set, яке може перевіряти значення або робити інші цікаві речі:

private int b;

public int B {
    get { return b; }
    set {
        if (value < 0) throw new ArgumentOutOfRangeException("value");
        b = value;
    }
}

Зверніть увагу, що більшість властивостей використовуватиме поле для зберігання їх значення. Властивості рідко існують самі по собі, крім полів.


4

Властивість - це своєрідний короткий геттер та або сеттер. Ви можете додати логіку до setабо getвласності або зробити їх приватними , що означає , що вони не доступні з боку виходу, де змінна завжди доступна (якщо це публічне).


4

У C # будь-яка "змінна", яка має геттер і сеттер, називається властивістю. Змінна не має геттерів і сеттерів, або приблизно так говорять у підручниках.

Мій інструктор з програмування змусив нас отримати геттери та сеттери майже для кожної змінної, яку ми створили на Java. Навіть індексуючи змінні, він змусив нас використовувати геттер і сеттер, якщо вони були оголошені в області глобального класу. Я думаю, що це могло бути надмірно, але це змусило мене зробити геттерів та сетерів.

Справжні речі щодо геттерів та сеттерів полягають у тому, що вони, швидше за все, роблять більше, ніж просто встановлюють внутрішню змінну. Більшість установників збираються виконати перевірку даних певного типу, щоб переконатись, що дані можуть бути встановлені як змінні. Отримувач може також перевірити дані, що повертаються, за деякими критеріями.

Якщо ваша власність є приватною, а ваші установники та отримувачі є загальнодоступними, технічно будь-хто може отримати доступ до вашої змінної та змінити її так, ніби він мав загальнодоступний доступ до фактичної змінної. Отже, насправді вам слід перевірити свої дані, щоб переконатися, що вони дійсні, або перевірити інші дані.

private int myVariable;
public int myVariable 
{
    get 
    { 
       return myVariable; 
    }
    set 
    {
        if (value < 0) 
        { 
           throw new Exception("This is your exception some where else in code");
        }
        myVariable = value; //remember value is something that is
                            //declared automatically
    }
}

public string FirstName { get; set; }

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

private string firstName;

public string FirstName
{
    get
    {
       //...code here
    }

    set
    {
       //...code here
    }
}

3

Змінна - це, ну, змінна.

Властивість - це особливий тип методу, який виставляє цю змінну. І оскільки це метод, отже, ви можете робити в ньому і деякі інші речі, окрім простого викриття змінної.

З MSDN:

Заява про майно вводить декларацію власності. Властивість може мати процедуру Get (лише читання), процедуру Set (лише запис) або обидва (читання-запис). Ви можете опустити процедуру отримання та встановлення, коли використовуєте властивість, яка автоматично реалізована. Для отримання додаткової інформації див. Автоматично реалізовані властивості (Visual Basic).

Ви можете використовувати Property лише на рівні класу. Це означає, що контекст оголошення для властивості повинен бути класом, структурою, модулем або інтерфейсом і не може бути вихідним файлом, простором імен, процедурою або блоком. Для отримання додаткової інформації див. Контексти декларації та рівні доступу за замовчуванням.

За замовчуванням властивості використовують загальнодоступний доступ. Ви можете налаштувати рівень доступу властивості за допомогою модифікатора доступу в операторі Property, а за бажанням ви можете налаштувати одну з його процедур властивостей на більш обмежений рівень доступу.


0

У вашому прикладі Aце відкрите поле класу ABCі Bє публічною власністю класу ABC. Зокрема, Bце властивість , яка автоматично реалізована . Це означає, що "під капотом" компілятор виконує частину роботи за вас і ефективно трансформує ваш код у:

public class ABC()
{
   private int b;

   public int A;
   public int B
   {
       get
       {
          return b;
       }
       set
       {
          b = value;
       }
   }
}

0

Змінна визначається в основному для доступу до значення з класу або до того самого класу відповідно до їх модифікатора, призначеного цій змінній.

Коли ми визначаємо властивість, існує два методи, створені для однієї властивості, тому генеруються додаткові накладні витрати, що є недоліком властивості.

Перевагами властивостей є отримання або встановлення значення в приватну змінну класу.


0

Існує дуже хороша стаття (посилання нижче) про використання полів / змінних проти Властивостей від самої Microsoft. Хоча в статті по суті йдеться про правило порушення FxCop, вона чітко визначає різницю між цими двома та точними рекомендаціями щодо використання.

Витяг із статті:

Основне використання поля має бути деталлю реалізації. Поля повинні бути приватними або внутрішніми, і їх слід виставляти за допомогою властивостей. Доступ до властивості настільки ж простий, як доступ до поля, і код у засобах доступу до властивості може змінюватися в міру розширення функцій типу, не вносячи змін.

Посилання: https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-3.0/ms182141(v=vs.80)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.