MostlyRenegade
#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?
  • Najlepsze
  • Wszystkie komentarze
markaron
@MostlyRenegade: W czym ci to przeszkadza że będzie wywoływana wielokrotnie? Brzmi jak jakaś mikro optymalizacja i próba rozwiązania wydumanego problemu.
markaron
@MostlyRenegade: W teorii ułatwia w praktyce komplikuje bo prowadzi do hierarchii powiązanych ze sobą klas co właśnie się prawdopodobnie wydarzyło w twoim projekcie. Poczytaj o kompozycji i przewadze kompozycji nad dziedziczeniem. Nie będę się tu rozpisywał bo jest masa informacji online. Tu masz z przykładem w C# https://code-maze.com/csharp-composition-vs-inheritance/
Krolik
Krolik
@MostlyRenegade:

Mam sobie klasę bazową i kilka klas potomnych


Już na starcie wygląda to źle. Dlaczego nie niezależne klasy i wspólny
markaron
@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ę
Krolik
Krolik
@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ą
WielkiElektronig
@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.
MostlyRenegade
MostlyRenegade Autor
0
@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
MostlyRenegade Autor
0
@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
MostlyRenegade Autor
0
@markaron: no ale jaki refactoring? I jak sobie radzisz bez dziedziczenia? Przecież to ułatwia wiele rzeczy.
uzytkownik_wykop_pl
uzytkownik_wykop_pl
@MostlyRenegade: Nikt ci nie broni miec jednego i drugiego w projekcie. Ale z dziedziczeniem często jest tak że w pewnym momencie tworzy się łańcuszek zależnosci który jest nie do ogarnięcia.
WyjmijKija
WyjmijKija
@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
Pacze69
Pacze69
@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.
xavhowk
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
MostlyRenegade
MostlyRenegade Autor
0
@xavhowk: no właśnie nie do końca. Na liście znajdują się tylko niektóre właściwości obiektu i do tego w ustalonej kolejności. Klasa bazowa nie na szans tego obsłużyć.
zibizz1
zibizz1
@MostlyRenegade: Ale w potomnych dodajesz w srodek te pola?
ja bym zrobił metode bazowa i nadpisywał w potomnych jesli chce coś dodac i dodawał na koniec
zibizz1
zibizz1
@MostlyRenegade: A jeszcze jeden sposób. Dodjasz sobie atrybut typu
[ExportProperty(Order=100)]
i zrób metode które pobiera properyInfo tylko z tym atrybutem i sortuj po Order i juz
MostlyRenegade
MostlyRenegade Autor
0
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.
Saly
Saly
0
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.
MostlyRenegade
MostlyRenegade Autor
0
@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.