Защо имам нужда от частно поле, което е изложено чрез публична собственост?

Идвам главно от света на Java. И така, свойствата на C# изглеждат добре.

Знам, че с C# 3.0 или по-нова версия мога да използвам автоматични свойства. Още повече ми харесва :).

Въпросът ми е за (може би по-стар) код, където мога да видя това:

   private int age;

   public int Age {

     get { return age; }
     set { age = value; }     
   }

Защо имам нужда от възрастта на частното поле? Какво наистина крия тук?

РЕДАКТИРАНЕ:

Напълно разбирам нуждата от гетер и сетер. Споменах, че идвам от света на Java и правя това през цялото време.

Разбирам, че автоматичните свойства в C# 3.0 или по-нови са синтатична захар. Но може би въпросът ми има по-прост отговор. Това означава ли, че (под C# 3.0) свойството не притежава никаква стойност. Значи трябва да получи стойността от някое друго поле?


person Bojan Milenkoski    schedule 27.01.2010    source източник
comment
Толкова много възможни дубликати. Ето един за начало stackoverflow.com/questions/295104/ и разбира се, статията на Джон Скийт: csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx   -  person David Hall    schedule 28.01.2010
comment
Както отбелязаха @Jay и @womp в отговорите си, не имате нужда от това изрично лично поле. Всъщност, ако вашият примерен код беше вашият действителен код, вие бихте използвали вместо това стенограмата на автоматичното свойство. Обикновено бихте предоставили изричната реализация на свойството само ако имате нужда от друга логика в get/set.   -  person JMD    schedule 28.01.2010
comment
Търсих SO, не намерих отговора си (и беше тук...). Направих търсене в Google, само полезна информация беше за използването на обществено поле спрямо публична собственост. Предполагам, че търсачките не ме харесват :). И проверката на правописа не ме харесва тук на SO. Всичко е червено... Просто не е моят ден.   -  person Bojan Milenkoski    schedule 28.01.2010


Отговори (11)


По-старите версии на C# нямаха автоматични свойства, така че трябваше да декларирате вашите променливи, спрямо които свойствата действат, както във вашия пример. В наши дни същият код може да се изрази като:

public int Age { get; set; }

Мисля, че това отговаря на въпроса ви. Ако обаче питате "защо просто да нямаме public int Age; и да позволим на програмистите да задават стойността директно в полето?", тогава:

Първото нещо, което трябва да имате предвид е, че инструментите за достъп до свойства се компилират в методи. Това означава, че има различен ABI от просто четене/запис на променлива член на класа, въпреки че може синтактично да изглежда по същия начин, както ако имате:

class Fu {
  public int Age;
}

И така, това означава, че ако в някакъв момент надолу по пътя трябва да добавите някакво известие, че полето Възраст се е променило - ако използвате свойства, можете лесно да добавите тази логика за известяване към инструмента за настройка на свойства, без да нарушавате ABI.

public int Age {
  get { return age; }
  set { age = value; NotifySomeOtherCode (); }
}

Ако започнете с публично поле, по-късно промяната му на свойство ще промени ABI, което е лошо за всяка програма(и), която може да зависи от вашето събрание. Така че е по-добре да започнете със свойствата.

Дано имам смисъл...

person jstedfast    schedule 27.01.2010
comment
Първият параграф беше отговорът, но винаги е хубаво да има нещо повече - person Bojan Milenkoski; 28.01.2010

Автоматичните свойства не се поддържаха в по-стари версии на C# компилатора.

Горният код е повече или по-малко еквивалентен на този (ако приемем, че полето всъщност никога не се използва директно):

public int Age {
  get;
  set;
}
person Lucero    schedule 27.01.2010

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

person Jay    schedule 27.01.2010

Стандартният отговор би бил „капсулиране на подробностите за изпълнението на това как и къде се съхранява възрастта“.

За целите на извличането по-реалистичен пример може да бъде, че един ден потенциално бихте могли да искате да получите достъп до стойността по начин, който означава, че директният достъп не е толкова добър. Например, ако това е стойност, която може да кеширате другаде, или ако е изчислена стойност.

От гледна точка на капсулирането на процеса на настройка, това означава, че можете да вградите известно валидиране на ниво модел в сетера; ако някой се опита да зададе концептуално невалидна стойност, можете да хвърлите IllegalArgumentException и да го отхвърлите.

В тези случаи капсулирането означава, че целият ви съществуващ код не трябва да се променя, защото е трябвало да опаковате стойността в нещо.

person Rob    schedule 27.01.2010

Автоматичните свойства в C#, когато се компилират, завършват функционално точно като горния код. Компилаторът генерира резервно поле за вас.

Така че имате нужда от нещо, подкрепящо свойство - поле или някакъв код - просто се грижи за вас с прекия път на автоматичните свойства.

person womp    schedule 27.01.2010
comment
точно не е вярно, действителното име на частното поле може да варира. - person Lucero; 28.01.2010
comment
Имам предвид, че функционално се компилира към едно и също нещо, а не че токените са еднакви. - person womp; 28.01.2010
comment
Въпросът ми е: каква е причината за частното поле? Добре, мога да променя името на частното поле (може да е всяко друго поле). Моята публична собственост е все същата и това е, което ще използвам в моя клас или ще изчисля някои други частни полета в собствеността. - person Bojan Milenkoski; 28.01.2010
comment
Това свойство е просто функция. Стойността трябва да бъде запазена някъде. Името няма значение. - person Dykam; 28.01.2010
comment
Благодаря. Бих искал да избера вашия коментар като отговор. - person Bojan Milenkoski; 28.01.2010

Свойствата са просто хубав начин да напишете двойка метод get и set. В Java бихте направили това:

private int age;

public int getAge() { return age; }
public void setAge(int value) { age = value; }

Имате нужда от частно поле, за да съхранявате възрастта някъде - getAge и setAge са само методи.

Същото важи и за C# за версии преди 3.0:

private int age;

public int Age
{
   get { return age; }
   set { age = value; } 
}

Това е метод за получаване и задаване, просто добре съчетани, така че можете да пишете x.Age = 21 вместо x.setAge(21).

С автоматичните свойства компилаторът на C# генерира частното поле за вас (но то все още е там!):

public int Age
{
   get;
   set;
}

Предимството на автоматичните свойства е, че вече не е необходимо сами да създавате резервното поле ръчно.

Предимството на ръчната версия е, че можете да добавите допълнителна логика към методите get и set, например валидиране на параметър:

private int age;

public int Age
{
   get { return age; }
   set { if (value < 0) throw new ArgumentException(); age = value; } 
}
person dtb    schedule 27.01.2010
comment
Мисля, че въпросът е повече за ползите от него? - person Rob; 28.01.2010

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

   private int age;

   public int Age {

     get { return age; }
     set { 
       age = value; 
       Log("value of age changed");
     }     
   }

С публично поле age трябваше да регистрирате това навсякъде в кода, където променяте стойността на възрастта.

person Fabiano    schedule 27.01.2010

В този случай вие не криете нищо, но това ще ви даде свободата да добавите get/set логика към вашето лично поле по-късно. Така че всеки, който използва имота, няма да забележи разликата в бъдеще.

person red.clover    schedule 27.01.2010

В простия случай нищо. Въпреки това вие улеснявате поддържането на интерфейса към класа, ако внедряването на някой от тези два метода изисква допълнителен код.

Вземете например, ако трябва да добавите променящо се събитие към сетера.

   public int Age {

     get { return age; }
     set { 
          if ( age != value) {
              age = value; 
              OnAgeChanged();
          }
      }     
   }

Можете да направите това със свойство и да не нарушавате клиентския код. Едно поле няма това предимство.

person dkackman    schedule 27.01.2010

С автоматичните свойства не трябва да правите това. Няма нищо лошо в това, но с автоматичните свойства все още ще имате своя подпис на собственост, което е важното. Преди автоматичните свойства трябваше да имате резервно поле за собствеността си. Докато имате автоматично свойство, можете по-късно да го промените във формат с изрично резервно поле и подписът остава същият.

Но няма нищо лошо в това. С изключение на това, че конвенцията става все по-често наричаща частното резервно поле "_age".

(Предполагам, че знаете защо искате да имате свойство, независимо дали автоматично или не, вместо публично поле. Причината е, че обектът има различен подпис, ако променете form public field на public property, така че е най-безопасно просто да започнете със свойство, дори ако няма допълнителна логика.)

person Patrick Karcher    schedule 27.01.2010

Getters и Setters са публичният интерфейс, с който другите класове взаимодействат. В сложни системи обикновено в крайна сметка извършвате валидиране и друга работа вътре в гетъра и сетера.

Частното поле е за вътрешна употреба. Ако трябва да промените стойността от вътрешността на класа, но да заобиколите цялата допълнителна работа, бихте променили частната променлива.

person Greg Bray    schedule 27.01.2010