W 2009 roku ta rada wydawała się po prostu przekleństwem odmiany Who Moved My Cheese . Dziś jest prawie śmiesznie przestarzały.
Jedną z bardzo ważnych kwestii, na którą wiele odpowiedzi wydaje się chodzić na palcach, ale nie do końca się do nich odnosi, jest to, że te rzekome „niebezpieczeństwa” związane z właściwościami są celową częścią projektu struktury!
Tak, nieruchomości mogą:
Określ różne modyfikatory dostępu dla metody pobierającej i ustawiającej. To przewaga nad polami. Powszechnym wzorcem jest posiadanie publicznego pobierającego i chronionego lub wewnętrznego ustawiacza, bardzo użytecznej techniki dziedziczenia, której nie można osiągnąć za pomocą samych pól.
Podaj wyjątek. Do tej pory jest to jedna z najskuteczniejszych metod walidacji, zwłaszcza podczas pracy ze strukturami interfejsu użytkownika, które obejmują koncepcje powiązań danych. O wiele trudniej jest zapewnić, że obiekt pozostanie w prawidłowym stanie podczas pracy z polami.
Wykonanie zajmie dużo czasu. Prawidłowe porównanie dotyczy metod , które zajmują równie dużo czasu - nie pól . Nie podano żadnej innej podstawy dla stwierdzenia „preferowana jest metoda” niż osobiste preferencje jednego autora.
Zwraca różne wartości z jego metody pobierającej w kolejnych wykonaniach. Wydaje się to prawie żartem w tak bliskiej odległości od punktu wychwalającego zalety ref
/ out
parametry z polami, których wartość pola po a ref
/out
wywołaniu jest prawie gwarantowana, że różni się od poprzedniej wartości, i to w sposób nieprzewidywalny.
Jeśli mówimy o konkretnym (i praktycznie akademickim) przypadku dostępu jednowątkowego bez połączeń doprowadzających, to jest całkiem dobrze zrozumiałe, że to po prostu zły projekt właściwości, aby mieć efekty uboczne zmieniające stan widzialny, a może moja pamięć jest zanikają, ale nie mogę sobie przypomnieć żadnych przykładów ludzi używających DateTime.Now
i oczekujących, że za każdym razem wyjdzie ta sama wartość. Przynajmniej nie ma żadnych przypadków, w których nie schrzaniliby tego tak samo źle z hipotetą DateTime.Now()
.
Wywołuj obserwowalne skutki uboczne - i to jest właśnie powód, dla którego właściwości zostały wymyślone przede wszystkim jako cecha języka. Wytyczne firmy Microsoft dotyczące projektowania właściwości wskazują, że kolejność ustawiaczy nie powinna mieć znaczenia, ponieważ w przeciwnym razie oznaczałoby to czasowe sprzężenie . Z pewnością nie można osiągnąć czasowego sprzężenia z samymi polami, ale to tylko dlatego, że nie można w ogóle spowodować żadnego znaczącego zachowania z samymi polami, dopóki nie zostanie wykonana jakaś metoda.
Metody dostępu do właściwości mogą w rzeczywistości pomóc w zapobieganiu niektórym typom sprzężeń czasowych przez wymuszenie na obiekcie prawidłowego stanu przed podjęciem jakiejkolwiek akcji - na przykład, jeśli klasa ma a StartDate
i an EndDate
, wówczas ustawienie EndDate
przed StartDate
może również wymusić StartDate
cofnięcie. Dzieje się tak nawet w środowiskach wielowątkowych lub asynchronicznych, w tym w oczywistym przykładzie interfejsu użytkownika sterowanego zdarzeniami.
Inne rzeczy, które mogą robić właściwości, których pola nie mogą obejmować:
- Ładowanie z opóźnieniem , jeden z najskuteczniejszych sposobów zapobiegania błędom kolejności inicjalizacji.
- Powiadomienia o zmianach , które są prawie całą podstawą architektury MVVM .
- Dziedziczenie , na przykład definiowanie klas abstrakcyjnych
Type
lub innych Name
klas pochodnych, może dostarczyć interesujących, ale jednak stałych metadanych o sobie.
- Przechwytywanie dzięki powyższemu.
- Indeksatory , które każdy, kto kiedykolwiek miał do czynienia z interopem COM i nieuniknionym wyrzucaniem
Item(i)
połączeń, uzna za cudowną rzecz.
- Pracuj z PropertyDescriptor, który jest niezbędny do tworzenia projektantów i ogólnie dla struktur XAML.
Richter jest wyraźnie płodnym autorem i wie dużo o CLR i C #, ale muszę powiedzieć, że wydaje się, że kiedy pierwotnie napisał tę poradę (nie jestem pewien, czy jest to w jego nowszych wersjach - mam szczerą nadzieję, że nie) że po prostu nie chciał porzucić starych nawyków i miał problemy z zaakceptowaniem konwencji C # (na przykład w porównaniu z C ++).
Rozumiem przez to, że jego argument o „właściwościach uważanych za szkodliwe” sprowadza się zasadniczo do jednego stwierdzenia: właściwości wyglądają jak pola, ale mogą nie działać jak pola. Problem z tym stwierdzeniem polega na tym, że nie jest ono prawdą lub w najlepszym przypadku jest bardzo mylące. Właściwości nie wyglądają jak pola - przynajmniej nie powinny wyglądać jak pola.
Istnieją dwie bardzo mocne konwencje kodowania w C # z podobnymi konwencjami wspólnymi dla innych języków CLR, a FXCop będzie na ciebie krzyczeć, jeśli ich nie będziesz przestrzegać:
- Pola powinny być zawsze prywatne, nigdy publiczne.
- Pola należy zadeklarować w camelCase. Właściwości to PascalCase.
W związku z tym nie ma niejednoznaczności co do tego, czy Foo.Bar = 42
jest to metoda dostępu do właściwości, czy do pola. Jest to metoda dostępu do właściwości i powinna być traktowana jak każda inna metoda - może być powolna, może zgłosić wyjątek, itp. Taka jest natura abstrakcji - to całkowicie zależy od klasy deklarującej, jak zareagować. Projektanci klas powinni stosować zasadę najmniejszego zaskoczenia, ale dzwoniący nie powinni niczego zakładać na temat nieruchomości poza tym, że robi to, co mówi na puszce. To jest celowe.
Alternatywą dla właściwości są wszędzie metody pobierające / ustawiające. Takie jest podejście Java i od samego początku było kontrowersyjne . W porządku, jeśli to twoja torba, ale po prostu tak nie jest w obozie .NET. Próbujemy, przynajmniej w ramach systemu statycznego, unikać tego, co Fowler nazywa szumem syntaktycznym . Nie chcemy dodatkowych nawiasów, dodatkowych get
/ set
brodawek ani dodatkowych sygnatur metod - nie, jeśli możemy ich uniknąć bez utraty przejrzystości.
Powiedz, co chcesz, ale foo.Bar.Baz = quux.Answers[42]
zawsze będzie to o wiele łatwiejsze do przeczytania niż foo.getBar().setBaz(quux.getAnswers().getItem(42))
. A kiedy czytasz tysiące linijek tego dnia, to robi różnicę.
(A jeśli twoją naturalną odpowiedzią na powyższy akapit jest powiedzenie „z pewnością trudno go przeczytać, ale byłoby łatwiej, gdybyś podzielił to na wiele wierszy”, to przykro mi, że całkowicie przegapiłeś ten punkt .)