Struktury i puste pola ułatwią współdziałanie z niektórymi niezarządzanymi interfejsami API. Często okazuje się, że interfejs API niskiego poziomu chce uzyskać dostęp do wartości przez odniesienie, co jest dobre dla wydajności (ponieważ unikamy niepotrzebnej kopii). Korzystanie z właściwości jest przeszkodą w tym i często biblioteki otoki wykonują kopie dla ułatwienia użytkowania, a czasem dla bezpieczeństwa.
Z tego powodu często uzyskuje się lepszą wydajność dzięki typom wektorów i macierzy, które nie mają właściwości, ale puste pola.
Najlepsze praktyki nie powstają w próżni. Pomimo pewnego kultu ładunków, ogólnie dobre praktyki istnieją z dobrego powodu.
W tym przypadku mamy kilka:
Właściwość umożliwia zmianę implementacji bez zmiany kodu klienta (na poziomie binarnym można zmienić pole na właściwość bez zmiany kodu klienta na poziomie źródłowym, jednak po zmianie kompiluje się do czegoś innego) . Oznacza to, że przy użyciu właściwości od samego początku kod, który odwołuje się do twojego, nie będzie musiał zostać ponownie skompilowany, aby zmienić to, co ta właściwość robi wewnętrznie.
Jeśli nie wszystkie możliwe wartości pól twojego typu są poprawnymi stanami, nie chcesz narażać ich na kod klienta, który kod go modyfikuje. Dlatego jeśli niektóre kombinacje wartości są nieprawidłowe, chcesz zachować pola prywatne (lub wewnętrzne).
Mówiłem kod klienta. To oznacza kod, który woła do twojego. Jeśli nie tworzysz biblioteki (lub nawet tworzysz bibliotekę, ale używasz wewnętrznej zamiast publicznej), zwykle możesz uciec od niej i trochę dobrej dyscypliny. W takiej sytuacji najlepsza praktyka korzystania z właściwości ma na celu zapobieganie strzelaniu sobie w stopę. Co więcej, o wiele łatwiej jest wnioskować o kodzie, jeśli widzisz wszystkie miejsca, w których pole może się zmienić w jednym pliku, zamiast martwić się czymkolwiek, czy nie jest modyfikowane gdzie indziej. W rzeczywistości właściwości są również dobre do ustalenia punktów przerwania, gdy zastanawiasz się, co poszło nie tak.
Tak, warto zobaczyć, co dzieje się w branży. Czy jednak masz motywację, by przeciwstawić się najlepszym praktykom? czy po prostu przeciwstawiasz się najlepszym praktykom - utrudniając zrozumienie kodu - tylko dlatego, że zrobił to ktoś inny? Ach, nawiasem mówiąc, „inni to robią” to sposób na rozpoczęcie kultu ładunków.
Więc ... Czy twoja gra działa wolno? Lepiej poświęć czas na znalezienie wąskiego gardła i naprawienie go, zamiast spekulacji, co to może być. Możesz być pewny, że kompilator dokona wielu optymalizacji, dlatego istnieje szansa, że patrzysz na niewłaściwy problem.
Z drugiej strony, jeśli decydujesz, od czego zacząć, powinieneś martwić się najpierw o algorytmy i struktury danych, zamiast martwić się o mniejsze szczegóły, takie jak pola vs właściwości.
Wreszcie, czy zarabiasz coś, postępując wbrew najlepszym praktykom?
Czy w przypadku konkretnego przypadku (Unity i Mono dla Androida) Unity przyjmuje wartości przez odniesienie? Jeśli nie, skopiuje wartości i tak, nie ma tam wzrostu wydajności.
Jeśli tak, jeśli przekazujesz te dane do interfejsu API, który zajmuje ref. Czy ma sens upublicznienie pola, czy można sprawić, by typ mógł bezpośrednio wywoływać interfejs API?
Tak, oczywiście, mogą istnieć optymalizacje, które można wykonać, używając struktur z nagimi polami. Na przykład, uzyskujesz do nich dostęp za pomocą wskaźników Span<T>
lub podobnych. Są również kompaktowe w pamięci, co ułatwia ich serializację w celu przesłania przez sieć lub umieszczenia w stałej pamięci (i tak, to są kopie).
A teraz, czy wybrałeś odpowiednie algorytmy i struktury, jeśli okażą się one wąskim gardłem, wtedy decydujesz, jaki jest najlepszy sposób, aby to naprawić ... które mogą być strukturami z nagimi polami lub nie. Będziesz mógł się tym martwić, jeśli i kiedy to się stanie. Tymczasem możesz martwić się ważniejszymi sprawami, takimi jak stworzenie dobrej lub fajnej gry, w którą warto grać.