Wpis z mikrobloga

#technologia #programowanie #csharp #programista15k

Hej programiści, poradźcie coś.

Mam sobie klasę bazową i kilka klas potomnych. W każdej z nich chcę mieć funkcję zwracającą listę wybranych właściwości (List<PropertyInfo>). Normalnie można to zrobić nadpisując po prostu metodę, ale ponieważ będzie ona wywoływana wielokrotnie wymyśliłem, że może ją zrobić statyczną, tym bardziej że lista taka będzie identyczna dla wszystkich instancji danej klasy. Problem w tym, że metod statycznych nie można nadpisywać. Można je niby ukrywać przez new, ale może jest jakiś lepszy i bardziej elegancki sposób?
  • 19
@MostlyRenegade: jak zwracaja to samo, to pewnie beda sie miedzy soba roznic tylko jakims filtrem. Moze nawet nie trzeba ich overridowac, tylko przyjmowac jakis filtr jako parametr wejsciowy? Ja bym zostawil tak jak jest. Ewentualnie mozesz wywalic ja do interfejsu: https://stackoverflow.com/questions/9415257/how-can-i-implement-static-methods-on-an-interface
ale jak napisal kolega wyzej, to juz jest przekombinowanie i szkoda energii.
@markaron: trochę tak. Powiadają, że mechanizmy refleksji są kosztowne, aczkolwiek pewnie nie będzie miało to aż tak wielkiego znaczenia. Pytam bardziej z ciekawości, jak byście podeszli do takiego zagadnienia. Może zupełnie inaczej zaprojektować relacje i klasy?
@MostlyRenegade:

Mam sobie klasę bazową i kilka klas potomnych


Już na starcie wygląda to źle. Dlaczego nie niezależne klasy i wspólny interfejs?

Normalnie można to zrobić nadpisując po prostu metodę, ale ponieważ będzie ona wywoływana wielokrotnie wymyśliłem, że może ją zrobić statyczną


No, a teraz robiąc takie fikołki odrąbujesz sobie obie nogi i ręce.

Po co chcesz tak robić i jaki masz konkretny problem ze zwykłą metodą? Skoro chcesz aby metoda
@MostlyRenegade: Ja unikam dziedziczenia jak mogę. Większość problemów (zwłaszcza biznesowych) da się zwykle rozwiązać inaczej niż dziedziczeniem. Problemem tutaj są przykłady które uczą dziedziczenia na przykładzie wydumanych problemów typu Car, Animal.

Więc albo przemyślenie i zaprojektowanie logiki od nowa i refaktoryzacja w kierunku kompozycji zamiast dziedziczenia (jeżeli masz taką możliwość, bo nie zawsze realia w projekcie na to pozwalają), albo zostawić tak jak jest.

Jeżeli cię to kopnie w dupę bo
@Krolik: w klasie bazowej są już pewne funkcjonalności, które są potrzebne również w klasach potomnych.
Wiem, że pola i metody nie mogą być statyczne dla zachowania polimorfizmu. Dlatego pytam, czy można to jakoś obejść. Chodzi mi właśnie o to, by dostać obiekt, który zależy w sumie od typu (klasy), a nie od instancji.
@MostlyRenegade: coś kombinujesz bez sensu. Po pierwsze pomyśl czy nie lepsze będzie mieć listę expressionów. Po drugie pomyśl czy nie użyć klasy generycznej. Bardziej nikt ci nie pomoże, bo nie wiadomo co chcesz zrobić. Chcesz konkretnej pomocy to napisz uproszczony kod
@MostlyRenegade: zrób sobie po prostu inicjalizację w runtime, i potem używaj raz zinicjalizowanej kolekcji.

Kolekcję zrób statyczną, zadbaj żeby się nie inicjalizowała wiele razy jednocześnie z wielu wątków jeśli trzeba i tyle.
Dlatego pytam, czy można to jakoś obejść. Chodzi mi właśnie o to, by dostać obiekt, który zależy w sumie od typu (klasy), a nie od instancji.


@MostlyRenegade: Jak chodzi tylko o typ, to może wystarczy stworzyć taką listę w konstruktorze w klasie bazowej, bo przez refleksje będziesz miał informacje o typie pochodnym, coś jak tu: https://dotnetfiddle.net/Voa78r
@xavhowk: @MostlyRenegade Jeżeli wynik ma być zależny od konkretnej klasy, a wspólny dla wszystkich instancji tej klasy, to:

- robisz statyczne pole trzymające tę listę propertiesów, inicjujesz ją w statycznym konstruktorze klasy
- robisz niestatyczną (czyli wirtualną) metodę zwracającą referencję do kolekcji z pola statycznego

Przy czym dobrze zadbać o to aby lista była niemutowalna i obiekty w tej liście również, aby uniknąć kuku jak ktoś ją będzie chciał zmodyfikować.

To
Dzięki panowie za podpowiedzi. Po dłuższej analizie problemu zostawiam jak jest, czyli bez pól i metod statycznych.
Jednocześnie wygląda na to, że trzeba będzie zupełnie ominąć zagadnienie stosując jakąś inną strukturę danych, ale to zostawię sobie na później. Najpierw funkcjonalność, potem refactoring.
w klasie bazowej są już pewne funkcjonalności, które są potrzebne również w klasach potomnych.


@MostlyRenegade: tak się nie robi. W podejściu z interfejsami wsadasz ten kod do jednej klasy. Te metody, które są zmienne wpychasz do osobnego interfejsu a twój obiekt ze stałymi metodami trzyma obiekt implementujący interfejs jako pole.
@Saly: ale dlaczego? Przecież właśnie na tym polega dziedziczenie. A interfejs nie ma tu prawie żadnej wartości dodanej. Poza tym, taka złożona struktura to potencjalnie dodatkowe problemy np. przy serializacji czy bindowaniu.