Właściwości automatyczne C # 3.0 - przydatne czy nie? [Zamknięte]


155

Uwaga: to zostało opublikowane, gdy zaczynałem C #. Mając wiedzę z 2014 roku, mogę naprawdę powiedzieć, że właściwości automatyczne należą do najlepszych rzeczy, jakie kiedykolwiek przydarzyły się językowi C #.

Jestem używany do tworzenia moich właściwości w C # przy użyciu pola prywatnego i publicznego:

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Teraz, dzięki .NET 3.0, mamy właściwości automatyczne:

public string Title { get; set; }

Wiem, że jest to bardziej pytanie filozoficzne / subiektywne, ale czy jest jakiś powód, aby używać tych właściwości automatycznych poza zapisaniem pięciu wierszy kodu dla każdego pola? Moim osobistym problemem jest to, że te właściwości ukrywają przede mną rzeczy, a ja nie jestem wielkim fanem czarnej magii.

W rzeczywistości ukryte pole prywatne nawet nie pojawia się w debugerze, co jest w porządku, biorąc pod uwagę fakt, że funkcje get / set nic nie robią. Ale kiedy chcę faktycznie zaimplementować jakąś logikę getter / setter, i tak muszę użyć pary prywatna / publiczna.

Widzę korzyść, że zapisuję dużo kodu (jeden na sześć wierszy) bez utraty możliwości późniejszej zmiany logiki pobierającej / ustawiającej, ale z drugiej strony mogę już to zrobić, po prostu deklarując pole publiczne „Public string Title” bez potrzeba {get; zestaw; }, co pozwala na zapisanie większej ilości kodu.

Więc czego tu brakuje? Dlaczego ktokolwiek miałby chcieć używać właściwości automatycznych?


86
„Moim osobistym problemem jest to, że te właściwości ukrywają przede mną różne rzeczy, a ja nie jestem wielkim fanem czarnej magii”. Co? WIESZ, że kompilator cały czas ukrywa przed Tobą tonę, prawda? O ile nie piszesz asemblera (a dokładniej, rzeczywiste 1 i 0 dla twojego kodu), WSZYSTKO, co piszesz, ukrywa przed tobą pewne rzeczy.
Charles Boyung

Odpowiedzi:



62

Tak, po prostu zapisuje kod. Znacznie łatwiej jest je odczytać, gdy jest ich dużo. Są szybsze w pisaniu i łatwiejsze w utrzymaniu. Zapisywanie kodu jest zawsze dobrym celem.

Możesz ustawić różne zakresy:

public string PropertyName { get; private set; }

Tak więc właściwość można zmienić tylko wewnątrz klasy. Nie jest to niezmienne, ponieważ nadal możesz uzyskać dostęp do prywatnego ustawiacza poprzez refleksję.

Od C # 6 można również tworzyć prawdziwe readonlywłaściwości - tj. Niezmienne właściwości, których nie można zmienić poza konstruktorem:

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

W czasie kompilacji stanie się to:

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

W niezmiennych klasach z wieloma członkami pozwala to zaoszczędzić wiele nadmiarowego kodu.


„Więc nie tracisz żadnej funkcjonalności”. jak je debugować?
wal

2
@wal - co tu jest do debugowania? Z tego punktu widzenia zasadniczo masz do czynienia ze zmiennymi składowymi.
Keith

6
@wal - Możesz umieścić na nich punkt przerwania, tak jak masz dostęp do zmiennej składowej, po prostu nie możesz do nich wejść. Ale dlaczego miałbyś tego chcieć? To, co faktycznie robią auto-właściwości, jest zarówno trywialne, jak i generowane automatycznie, jeśli masz błędy, jest to jedno z miejsc, w których są one bardzo mało prawdopodobne.
Keith,

3
być może będziemy musieli zabrać to poza Keith. :)
wal

1
Ale ok, załóżmy, że masz wiele wywołań setterów do myObj.Title ... chcesz zobaczyć, gdzie wartość zmienia się z „text” na null, czyli warunkowy punkt przerwania. jak to osiągniesz? nie możesz nawet ustawić punktu przerwania na seterze
wal

45

Trzy poważne wady używania pól zamiast właściwości to:

  1. Nie możesz powiązać danych z polem, podczas gdy możesz z właściwością
  2. Jeśli zaczniesz od pola, nie możesz później (łatwo) zmienić go na właściwość
  3. Istnieje kilka atrybutów, które możesz dodać do właściwości, których nie możesz dodać do pola

7
„Jeśli zaczniesz od pola, nie możesz później (łatwo) zmienić go na właściwość”, przepraszam, ale dlaczego?
Homam,

6
@Homam Zasadniczo każdy kod konsumencki, który używa odbić na twoich polach, zepsułby się, ponieważ musiałby przejść z używania FieldInfo do PropertyInfo.
WCWedin,

8
@Homam Ponadto zmiana pola na właściwość narusza zgodność binarną, co wymaga ponownej kompilacji wszystkich użytkowników pola.
Odrade

1
Pomijając problemy z rekompilacją i odbiciem, bardzo łatwo jest hermetyzować pola za pomocą programu Visual Studio: Ctrl-R + E umożliwia przekształcenie pola we właściwość z odpowiednimi metodami pobierającymi / ustawiającymi. (lub kliknij prawym przyciskiem myszy pole, ponownie rozfaktoryzuj, enkapsuluj pole).
JoeBrockhaus

Pola @Hommam to l-wartości (są to zmienne), a właściwości nie. Rzeczy, które mogły zostać skompilowane, gdy było to pole, mogą nie zostać skompilowane, gdy są właściwością.
Mark

29

Osobiście uwielbiam nieruchomości samochodowe. Co jest złego w zapisywaniu linii kodu? Jeśli chcesz robić coś w getterach lub setterach, nie ma problemu z konwersją ich później do normalnych właściwości.

Jak powiedziałeś, możesz użyć pól, a jeśli chcesz później dodać do nich logikę, przekonwertuj je na właściwości. Może to jednak stwarzać problemy z jakimkolwiek wykorzystaniem refleksji (i być może gdzie indziej?).

Właściwości pozwalają także ustawić różne poziomy dostępu dla metody pobierającej i ustawiającej, których nie można zrobić z polem.

Myślę, że to to samo, co słowo kluczowe var. Kwestia osobistych preferencji.


29

Bjarne Stroustrup, twórca C ++:

Szczególnie nie lubię zajęć z wieloma funkcjami get i set. To często wskazuje, że w ogóle nie powinna to być klasa. To tylko struktura danych. A jeśli naprawdę jest to struktura danych, zrób z niej strukturę danych.

I wiesz co? On ma rację. Jak często po prostu zawijasz pola prywatne w get and set, bez robienia czegokolwiek w get / set, po prostu dlatego, że jest to czynność „obiektowa”. To jest rozwiązanie problemu firmy Microsoft; są to w zasadzie pola publiczne, do których można się przypisać.


2
Naprawdę uważam, że to powinno mieć więcej punktów. Zbyt wielu ludzi postrzega właściwości automatyczne jako zielone światło do pisania okropnie zamkniętych (lub wcale nie zahermetyzowanych) klas, które są niczym więcej niż gloryfikowaną dziedziną publiczną. Oczywiście jest to bardziej problem związany z tym, jak ludzie używają tego narzędzia, a nie z samym narzędziem, ale myślę, że warto o tym wspomnieć, omawiając ogólnie właściwości.
sara

18

Wydaje się, że nikt nie wspomniał o tym, że właściwości automatyczne nie są niestety przydatne w przypadku niezmiennych obiektów (zwykle niezmiennych struktur). Ponieważ w tym celu naprawdę powinieneś zrobić:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(gdzie pole jest inicjowane w konstruktorze za pośrednictwem przekazanego parametru, a następnie jest tylko do odczytu).

Więc ma to zalety w porównaniu z prostym get/ private setautoperty.


Jeśli masz strukturę, zmiana dowolnej właściwości powoduje powstanie nowej struktury. Byłoby to problemem tylko wtedy, gdybyś chciał mieć wewnętrznie niezmienny typ referencyjny - nie widzę powodu, dla którego kiedykolwiek byś go potrzebował.
Keith

@Keith: Twoje pierwsze zdanie wydaje się nieprawdziwe.
Domenic

3
Czy nie public string Title { get; private set; }spowodowałoby to dokładnie tego samego? Oczywiście możesz to zmienić z poziomu klasy, ale jeśli to zrobisz, będziesz mieć inne problemy ...: p
Svish

2
@Svish - przez ten argument słowo kluczowe readonly w C # nigdy nie powinno być używane, ponieważ jego użycie oznaczałoby, że ukrywaliśmy te "różne problemy"
Zaid Masud

2
Chodzi mi tylko o to, że z zewnętrznego widoku API nie miałoby to większego znaczenia. I tak, w razie potrzeby, można by użyć właściwości auto. Najlepiej byłoby oczywiście, gdybyś mógł zrobić coś takiegopublic string Title { get; private readonly set; }
Svish,

12

Zawsze tworzę właściwości zamiast pól publicznych, ponieważ możesz używać właściwości w definicji interfejsu, nie możesz używać pól publicznych w definicji interfejsu.


8

Właściwości automatyczne są tak samo czarną magią, jak wszystko inne w C #. Kiedy pomyślisz o tym w kategoriach kompilacji do IL, a nie rozszerzania go do normalnej właściwości C #, to jest o wiele mniej czarnej magii niż wiele innych konstrukcji językowych.


5

Cały czas używam właściwości automatycznych. Przed C # 3 nie mogłem zawracać sobie głowy pisaniem i po prostu użyłem zmiennych publicznych.

Jedyne, czego mi brakuje, to możliwość zrobienia tego:

public string Name = "DefaultName";

Musisz przenieść wartości domyślne do swoich konstruktorów z właściwościami. żmudne :-(


4
Dzięki inicjalizatorom właściwości automatycznych w języku C # 6 wkrótce będzie można to zrobić: public string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Carlos Muñoz

5

Myślę, że każda konstrukcja, która jest intuicyjna ORAZ redukuje linie kodu, jest dużym plusem.

To właśnie te cechy sprawiają, że języki takie jak Ruby są tak potężne (to i dynamiczne funkcje, które również pomagają zredukować nadmiar kodu).

Ruby miał to przez cały czas jako:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

Jedyny problem jaki mam z nimi to to, że nie idą wystarczająco daleko. W tej samej wersji kompilatora, która dodała właściwości automatyczne, dodano metody częściowe. Dlaczego nie połączyli tych dwóch razem, jest poza mną. Prosta „częściowa zmiana na <PropertyName>” sprawiłaby, że te rzeczy byłyby naprawdę przydatne.


Możesz umieścić wiele metod częściowych wewnątrz innej metody. Stworzenie dla nich jakiegoś automatycznego wzorca byłoby mylące.
Matthew Whited

2

To proste, krótkie i jeśli chcesz stworzyć prawdziwą implementację wewnątrz ciała właściwości gdzieś w dół, nie zepsuje to zewnętrznego interfejsu twojego typu.

Tak proste jak to.


1

Należy tu zauważyć, że według mojego zrozumienia jest to po prostu cukier syntaktyczny na końcu języka C # 3.0, co oznacza, że ​​IL generowany przez kompilator jest taki sam. Zgadzam się co do unikania czarnej magii, ale mimo wszystko mniej wierszy na to samo jest zazwyczaj dobrą rzeczą.


1

Moim zdaniem należy zawsze używać właściwości automatycznych zamiast pól publicznych. To powiedziawszy, oto kompromis:

Zacznij od pola wewnętrznego przy użyciu konwencji nazewnictwa, której użyjesz dla właściwości. Kiedy pierwszy raz

  • potrzebują dostępu do pola spoza jego zespołu, lub
  • trzeba dołączyć logikę do metody pobierającej / ustawiającej

Zrób to:

  1. zmienić nazwę pola
  2. uczyń to prywatnym
  3. dodać właściwość publiczną

Twój kod klienta nie będzie musiał się zmieniać.

Jednak pewnego dnia Twój system będzie się rozrastał i rozłożysz go na osobne zestawy i wiele rozwiązań. Kiedy tak się stanie, wszystkie ujawnione pola wrócą, aby cię prześladować, ponieważ, jak wspomniał Jeff, zmiana pola publicznego na właściwość publiczną jest przełomową zmianą interfejsu API .


0

Używam CodeRush, jest szybszy niż właściwości automatyczne.

Aby to zrobić:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Wymaga łącznie ośmiu naciśnięć klawiszy.


5
Jeśli przytrzymam CTRL i V, mogę wkleić wiele, wiele rzeczy, / bardzo szybko /, ale to nie czyni tego „lepszym”. Jak to odpowiada na pierwotne pytanie?
JBRWilkinson,

0

W przypadku fragmentów kodu właściwość automatyczna o tej samej nazwie oznaczałaby łącznie siedem naciśnięć klawiszy;)


0

@Domenic: Nie rozumiem ... czy nie możesz tego zrobić z właściwościami automatycznymi ?:

public string Title { get; }

lub

public string Title { get; private set; }

Czy to jest to, o czym mówisz?


Możesz (to drugie; to pierwsze się nie skompiluje), ale wtedy pole nie jest niezmienne wewnątrz twojego obiektu.
Domenic,

Uwaga, tylko struktury są niezmienne, gdy są oznaczone jako tylko do odczytu, klasy są po prostu nieprzypisane.
Guvante

0

Moim największym problemem związanym z właściwościami automatycznymi jest to, że zostały zaprojektowane, aby zaoszczędzić czas, ale często muszę później rozszerzyć je do pełnowymiarowych właściwości.

To, czego brakuje VS2008, to refaktoryzacja właściwości automatycznej eksplodującej.

Fakt, że mamy enkapsulowany refaktor pola sprawia, że ​​mój sposób pracy jest szybszy, aby po prostu używać pól publicznych.

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.