Pola publiczne a właściwości automatyczne


353

Często mówi się nam, że powinniśmy chronić enkapsulację, tworząc metody getter i setter (właściwości w języku C #) dla pól klas, zamiast wystawiać pola na świat zewnętrzny.

Ale wiele razy pole jest tam tylko po to, by przechowywać wartość i nie wymaga obliczeń, aby uzyskać lub ustawić. Dla tych wszystkich zrobilibyśmy tę liczbę:

public class Book
{
    private string _title;

    public string Title
    {
          get{ return _title;  }
          set{ _title = value; }
    }
}

Cóż, mam spowiedź, nie mogłem znieść pisania tego wszystkiego (tak naprawdę nie musiałem tego pisać, musiałem na to popatrzeć), więc zbuntowałem się i korzystałem z publicznych pól.

Potem pojawia się C # 3.0 i widzę, że dodali właściwości automatyczne:

public class Book
{
    public string Title {get; set;} 
}

co jest bardziej uporządkowane i jestem za to wdzięczny, ale tak naprawdę, co takiego różni się od zwykłego tworzenia pola publicznego?

public class Book
{
    public string Title;
}


6
Przekształciłem cechę w właściwość tylko po to, abym mógł ustawić punkt przerwania dla setera
Ian Ringrose

1
Mam tendencję do robienia czegokolwiek, co nie jest własnością prywatną, ponieważ uświadomienie sobie, że muszę przekształcić pole w nieruchomość, doprowadziło do niepotrzebnego bólu głowy. Właściwości, pola i metody. O mój! przywołuje niezgodność, która gryzła mnie w przeszłości.
Steven Wexler

2
propFragment kodu pozwala szybko tworzyć właściwości. Po prostu wpisz propi tab.
Tono Nam

Odpowiedzi:


175

W pokrewnym pytaniu, które miałem jakiś czas temu, był link do posta na blogu Jeffa, wyjaśniający pewne różnice.

Właściwości a zmienne publiczne

  • Odbicie działa inaczej na zmiennych i właściwościach, więc jeśli polegasz na odbiciu, łatwiej jest używać wszystkich właściwości.
  • Nie można powiązać danych ze zmienną.
  • Zmiana zmiennej na właściwość jest przełomową zmianą. Na przykład:

    TryGetTitle(out book.Title); // requires a variable

24
„Zmiana zmiennej na właściwość jest przełomową zmianą”. Dotyczy to oczywiście tylko pisania biblioteki wielokrotnego użytku, czego nie robi większość programistów .
Steven

30
Ponadto właściwości, nawet właściwości automatyczne, mogą być wirtualne, a pola nie. Tak więc klasa podstawowa może mieć prostą implementację pola bazowego wygenerowaną przez kompilator dla auto-prop, podczas gdy klasy pochodne mogą wykonywać dodatkowe sprawdzanie poprawności lub inne operacje logiczne / obliczenia.
KeithS,

28
Również pole jest zmienną i może być przekazywane przez referencję ( reflub outsłowo kluczowe), podczas gdy właściwość jest parą akcesoriów i nie może być przekazana przez referencję. Na przykład, bool success = TryGetMyTitle(out myBook.Title);które zastosowania outbędą działać z polem, a nie z właściwością. To wyraźny przykład tego, dlaczego zmiana z pola na właściwość jest przełomową zmianą!
Jeppe Stig Nielsen

2
@KyleBaran Nie, to nie ma większego sensu, ponieważ właściwość jest parą metod akcesorów, a nie zmienną. Zwykle należy zadeklarować zmienną lokalną (ewentualnie odczytać właściwość i wstawić jej wartość do zmiennej lokalnej), przekazać zmienną lokalną jako ref/ out, a następnie ustawić właściwość na wartość, którą ma zmienna lokalna. Ale wtedy wywoływana metoda sama nie uzyskuje dostępu do właściwości, uzyskuje dostęp do lokalnej zmiennej, którą tam utworzyłeś.
Jeppe Stig Nielsen

5
@ theheserserker Prawda, chociaż w C # 6 możesz zrobić, public int Foo { get; }co spowoduje utworzenie właściwości automatycznej z polem tylko do odczytu.
Michael Stum

83

Ignorując problemy z interfejsem API, najcenniejszą rzeczą w korzystaniu z właściwości jest debugowanie.

Debuger CLR nie obsługuje punktów przerwania danych (większość macierzystych debugerów to robi). Dlatego nie jest możliwe ustawienie punktu przerwania dla odczytu lub zapisu określonego pola w klasie. Jest to bardzo ograniczone w niektórych scenariuszach debugowania.

Ponieważ właściwości są implementowane jako bardzo cienkie metody, możliwe jest ustawienie punktów przerwania na odczyt i zapis ich wartości. To daje im dużą nogę nad polami.


2
Dziesięć lat później są już punkty przerwania danych, przynajmniej dla .NET Core :)
Luaan

72

Zmiana pola na właściwość powoduje zerwanie kontraktu (np. Wymaga ponownej kompilacji całego kodu odniesienia). Więc kiedy masz punkt interakcji z innymi klasami - dowolnym publicznym (i ogólnie chronionym) członkiem, chcesz zaplanować przyszły rozwój. Rób to zawsze, używając właściwości.

Nie ma dziś nic, co mogłoby uczynić z niego auto-własność, a 3 miesiące później zdałem sobie sprawę, że chcesz sprawić, by był leniwy i wystawił kontrolę zerową w getterze. Jeśli użyłeś pola, jest to zmiana rekompilacji w najlepszym wypadku, aw najgorszym niemożliwa, w zależności od tego, kto i co jeszcze zależy od twoich zespołów.


9
Podobała mi się ta odpowiedź, ponieważ nie używa słów „odbicie”, „interfejs” ani „przesłonięcie”. (szkoda, jeśli chodzi o „kontrakt”)

65

Tylko dlatego, że nikt o tym nie wspominał: nie można definiować pól w interfejsach. Tak więc, jeśli musisz wdrożyć określony interfejs, który definiuje właściwości, auto-właściwości czasami są naprawdę fajną funkcją.


1
Powiedziałbym, że jeśli potrzebujesz interfejsu definiującego właściwości, powinna to być klasa abstrakcyjna. To, że c # pozwala definiować właściwości w interfejsach, nie oznacza, że ​​powinieneś ich używać. To zły projekt.
Odys

8
@odyodyodys - Nie jestem pewien, czy zgadzam się, że jest to zły projekt. Proszę wyjaśnić swoje uzasadnienie?
Zaid Masud

4
@odyodyodys Zgadzam się z zooone9243: Imp, z punktu widzenia projektu, nie ma różnicy między deklarowaniem własności a deklarowaniem pary getter / setter (co jest powszechną praktyką w przypadku interfejsów).
MartinStettner,

22
@ zooone9243, + MartinStettner: To było 6 miesięcy temu, od tego czasu wiele się nauczyłem. Odbieram to :)
Odys

47

Ogromna różnica, która jest często pomijana i nie jest wymieniona w żadnej innej odpowiedzi: zastąpienie . Możesz zadeklarować właściwości wirtualne i zastąpić je, podczas gdy nie możesz zrobić tego samego dla publicznych pól członkowskich.


10

Chodzi o wersjonowanie i stabilność API. Nie ma różnicy w wersji 1 - ale później, jeśli zdecydujesz, że musisz to uczynić właściwością z pewnego rodzaju sprawdzaniem błędów w wersji 2, nie musisz zmieniać interfejsu API - żadnych zmian kodu, gdziekolwiek, poza definicja nieruchomości.


10

Kolejną zaletą automatycznie zaimplementowanych właściwości w porównaniu z polami publicznymi jest to, że można ustawić prywatnie lub chroniony zestaw akcesoriów, zapewniając klasę obiektów, w których zdefiniowano, lepszą kontrolę niż w przypadku pól publicznych.


8

W tworzeniu pola nie ma nic złego public. Ale pamiętaj, tworząc getter/setterz privatepól ma enkapsulacji. IMO, jeśli nie przejmujesz się innymi funkcjami Property, równie dobrze możesz to zrobić public.


1

Jeśli później zdecydujesz się sprawdzić, czy tytuł jest unikalny, porównując z kolekcją lub bazą danych, możesz to zrobić we właściwości bez zmiany zależnego od niej kodu.

Jeśli wybierzesz tylko atrybut publiczny, będziesz mieć mniejszą elastyczność.

Dodatkowa elastyczność bez zerwania umowy jest dla mnie najważniejsza w korzystaniu z właściwości i, dopóki faktycznie nie potrzebuję elastyczności, automatyczne generowanie ma sens.


0

Jedną z rzeczy, które uważam za bardzo przydatne, podobnie jak cały kod i powody testowania, jest to, że jeśli jest to właściwość kontra pole, to Visual Studio IDE pokazuje referencje do właściwości, ale nie pola.


0

Mój pow później zrobił kilka badań

  1. Uprawomocnienie.
  2. Zezwalaj na przesłanianie akcesorium, aby zmienić zachowanie właściwości.
  3. Cel debugowania. Będziemy mogli dowiedzieć się, kiedy i co zmieni właściwość, ustawiając punkt przerwania w akcesorium.
  4. Możemy mieć pole tylko do ustawiania. Na przykład public set () i private get (). Nie jest to możliwe w polu publicznym.

To naprawdę daje nam więcej możliwości i możliwości rozszerzenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.