Kiedy należy umieścić dane typu Klucz / Wartość we własnej klasie zamiast korzystać ze wstępnie zbudowanej struktury ogólnej, takiej jak a KeyValuePair
lub a Tuple
?
Na przykład większość tworzonych przeze mnie pojemników ComboBox zawiera DisplayName i Value. Jest to rodzaj danych, które próbuję zdecydować, kiedy wprowadzić nową klasę, a kiedy tylko użyć KeyValuePair.
Obecnie pracuję nad czymś, co wykorzystuje iCalendar
, a dane wybranego użytkownika ostatecznie zostają połączone w key1=value1;key2=value2;
rodzaj ciągu. Zacząłem od umieszczenia danych w KeyValuePair<string,string>
, ale teraz zastanawiam się, czy powinna to być własna klasa.
Ogólnie rzecz biorąc, jestem zainteresowany ustaleniem, jakie wytyczne są stosowane przy podejmowaniu decyzji o użyciu istniejącej struktury / klasy, takiej jak obiekt o KeyValuePair
ponad 2 właściwościach, oraz w jakich sytuacjach zastosowalibyście jeden nad drugim.
źródło
tuple
typ.iCalendar
i chciałem mieć przedmioty dlaBYDAY
iBYSETPOS
. Pojawiają się w ComboBox, ale rzeczywiste dane są łączone w ciąg regułu, który jestkey=value;
rodzajem ciąguOdpowiedzi:
W większości przypadków używałbym raczej obiektu niż KeyValuePair lub Tuple. Po pierwsze, kiedy przyjdziesz po 6 miesiącach, aby wprowadzić zmiany, łatwiej jest dowiedzieć się, co było wcześniej, niż zastanawiać się, co to
Tuple t
jest i dlaczego ma te śmieszne wartości. Po drugie, w miarę jak wszystko rośnie i zmienia się, możesz łatwo nadać swojemu prostemu obiektowi do przesyłania danych zachowanie zgodnie z wymaganiami. Potrzebujesz dwóch formatów nazw? Łatwo, po prostu dodaj odpowiednie przeciążenia ToString (). Potrzebujesz go do wdrożenia interfejsu? Nie ma problemu. Wreszcie, tworzenie prostego obiektu jest praktycznie zerowe, zwłaszcza z automatycznymi właściwościami i uzupełnianiem kodu.Bonus Protip: jeśli chcesz uchronić te obiekty przed zanieczyszczeniem przestrzeni nazw, tworzenie prywatnych klas wewnątrz klas to świetny sposób na utrzymanie wszystkiego w tajemnicy i zapobieganie dziwnym zależnościom.
źródło
Zasada definiowania nowej klasy jest prosta: podsumowano ją w „Razor Razam”.
http://c2.com/cgi/wiki?OccamsRazor
Nie wprowadzaj nowych zajęć bez uzasadnionego powodu. Lub korzystaj z gotowych klas w jak największym stopniu. Lub wymyśl jak najmniej. Jednak możesz pisać mniej kodu.
Nie możesz użyć wstępnie zbudowanej klasy, jeśli musisz przypisać obiektowi wyjątkową odpowiedzialność, a odpowiedzialność ta nie jest zdefiniowana w klasie wstępnie zbudowanej. Często jest to unikalna metoda.
A
tuple
lubKeyValuePair
jest preferowany.Aż do.
Potrzebujesz funkcji, która nie jest częścią A
tuple
lubKeyValuePair
. Następnie musisz zdefiniować własną klasę.źródło
tuple
aniKeyValuePair
”? KeyValuePair ma przynajmniej pewną ograniczoną semantykę, ale krotki rzadko mają (może być możliwe, w zależności od kontekstu) imho. Wprowadzenie nowej klasy powinno oczywiście dać ci wyraźną semantykę.Jeśli piszesz własną klasę, masz jasne miejsce na umieszczenie dokumentacji na temat tych dwóch wartości. Zwłaszcza, że dwa ciągi nie są bardzo jasną definicją. Możesz jednak napisać coś takiego
źródło
MyPair
określa, jakie są wartości Tuple i do czego są używane.Item1
iItem2
! Czy nie jest tak łatwo zdefiniować całą klasę?public class SideStrings { public string Left { get; set; } public string Right { get; set; } }
S.Lott napisał
Pozwól mi powiedzieć, dlaczego mam z tym poważny problem. Od
wydaje się być w porządku .... czy KeyValue [ciąg, KeyValue [ciąg, KeyValuePair [ciąg, ciąg]]] też jest w porządku? Nie wiem, co powie S.Lott na ten temat, ale mój szef uważa, że to w porządku.
Odważę się nie zgodzić. I oto dlaczego: Zmniejsza czytelność kodu, który nastąpi. Funkcja, która wypełni taką strukturę danych, będzie o wiele bardziej złożona i podatna na błędy (bła ... wyjątek) (wyobraź sobie przynajmniej trochę logiki biznesowej). Nie kłóciłem się zbytnio z moim szefem, ale powiem to tutaj: Czytelność przewyższa oszczędność miejsca w minutach (co było jego argumentem). Więc nie byłby to obiekt klasy, w którym są pewne pola; ale niektóre pozostają puste, a czasem lepsze?
PS Jestem Ultra_Noob, więc powiedz mi, jeśli się mylę.
źródło
KeyValuePair<string,string>
to w porządku, zakładając, że rzeczy wprowadzone są w rzeczywistości kluczami i wartościami. Ponowne użycie istniejącej klasy jest zaletą, ponieważ oszczędzasz pisania kodu i zyskujesz interoperacyjność. OTOH, używanie czegoś tak skomplikowanego, jakKeyValuePair<string,KeyValuePair<string,string>>
jest przez większość czasu, jest po prostu zbyt skomplikowane, aby było praktyczne. Czasami może być słuszne - gdy nie potrzebujesz żadnej dodatkowej funkcjonalności, kiedy znaczenie jest oczywiste i kiedy działa dobrze z innymi klasami. YMMV, to tylko ważenie zalet i przeciwieństw.Kiedy mówimy parę klucz / wartość , zwykle myślę o tabelach mieszających lub tablicach asocjacyjnych lub po prostu obiekcie KeyValuePair . Używam ich wszystkich i nie ma różnicy, kiedy ich używam.
Myślę, że najważniejszą rzeczą w liście par klucz / wartość jest to, że klucze powinny być unikalne (ponieważ w końcu to klucz), a wszystkie wyżej wymienione struktury naprawdę zapewniają mi tę funkcjonalność.
Poza tym chcę wyszukiwać według kluczy lub wykonywać akcje w stylu listy (tablica), takie jak push i pop.
Zatem moja odpowiedź brzmi: NIE i nie tworzę obiektów jawnie dla par klucz / wartość, ponieważ wiele wbudowanych struktur już to dla mnie robi.
źródło
Rozdział szósty czystego kodu zawiera dobry opis tego, kiedy użyć struktury danych w porównaniu do klasy. W skrócie, używasz struktury danych, gdy w większości oczekujesz dodania nowych funkcji do obsługi tych danych. Korzystasz z klasy, gdy w większości oczekujesz dodania nowych typów danych, które będą obsługiwane przez istniejące funkcje. Twój ComboBox jest przykładem tego ostatniego. Masz jeden zestaw funkcji (implementacja ComboBox) działający na wielu różnych typach danych (różne rodzaje danych dla różnych widżetów).
źródło
Być może zgodziłbym się tutaj z Wildingiem , ale jestem też trochę noobem w tego rodzaju sprawach.
Sugerowałbym, że wbudowane typy są często obiektami mechanizmu . Na przykład KeyValuePair jest częścią mechanizmu słownika i tablic skrótów, pomagając zapewnić unikalne klucze i mają właściwości, które mają znaczące nazwy w kontekście samego mechanizmu.
Z drugiej strony użycie niestandardowych obiektów danych zapewnia lepszą reprezentację danych i zapewnia wiele korzyści, w tym czytelność i rozszerzalność. Nic nie stoi na przeszkodzie, aby ponownie wykorzystać istniejący kod w niestandardowych obiektach, jak sugeruje Sign , ale spróbuję ukryć zawiniętą klasę i uniknąć wycieku abstrakcji , abyś mógł później zmienić podstawową implementację bez wpływu na resztę kodu .
Więc prawdziwe pytanie: czy reprezentujesz dane, czy używasz danych w mechanizmie? (i nie radziłbym mieszać tych pojęć razem).
Z mojego doświadczenia wynika, że nie ma nic gorszego niż obserwowanie, że krotka [ciąg, ciąg] jest przekazywana do metody i nie ma bezpośredniego sposobu, aby dowiedzieć się, czym powinny być pozycje Item1 i Item2. Najlepiej używać Tuples w ramach metod lub tylko jako prywatni członkowie klasy.
źródło