MSDN mówi, że powinieneś używać struktur, gdy potrzebujesz lekkich obiektów. Czy istnieją inne scenariusze, w których struktura jest lepsza niż klasa?
Niektórzy ludzie mogli zapomnieć, że:
- Struktury mogą mieć metody.
- Struktury nie mogą być dziedziczone.
Rozumiem techniczne różnice między strukturami i klasami, po prostu nie mam pojęcia, kiedy użyć struktury.
Odpowiedzi:
MSDN ma odpowiedź: Wybieranie między klasami i strukturami .
Zasadniczo na tej stronie znajduje się 4-elementowa lista kontrolna i mówi, aby użyć klasy, chyba że Twój typ spełnia wszystkie kryteria.
źródło
ref
parametry, ilekroć jest to uzasadnione. Przekaż struct z 4000 pól jako parametr ref do metody, która zmienia jedno będzie tańsze niż przekazanie struct z 4 polami pod względem wartości do metody, która zwraca zmodyfikowaną wersję.Dziwi mnie, że nie przeczytałem żadnej z poprzednich odpowiedzi na to pytanie, które uważam za najważniejszy aspekt:
Używam struktur, gdy chcę typ bez tożsamości. Na przykład punkt 3D:
Jeśli masz dwa wystąpienia tej struktury, nie przejmujesz się, czy są to pojedyncze dane w pamięci, czy dwa. Troszczysz się tylko o wartości, które posiadają.
źródło
return false
jest to, co powinno być, poprawianie teraz.Bill Wagner ma rozdział na ten temat w swojej książce „skuteczny c #” ( http://www.amazon.com/Effective-Specific-Ways-Improve-Your/dp/0321245660 ). Kończy, stosując następującą zasadę:
źródło
Użyj struktury, gdy chcesz semantykę typu wartości zamiast typu odniesienia. Struktury są kopiowane według wartości, więc bądź ostrożny!
Zobacz także poprzednie pytania, np
Jaka jest różnica między strukturą a klasą w .NET?
źródło
Używałbym struktur, gdy:
obiekt ma być tylko do odczytu (za każdym razem, gdy przekazujesz / przypisujesz strukturę, jest on kopiowany). Obiekty tylko do odczytu są świetne, jeśli chodzi o przetwarzanie wielowątkowe, ponieważ w większości przypadków nie wymagają blokowania.
przedmiot jest mały i krótkotrwały. W takim przypadku istnieje duża szansa, że obiekt zostanie przydzielony na stosie, co jest znacznie bardziej wydajne niż umieszczenie go na zarządzanej stercie. Co więcej, pamięć przydzielona przez obiekt zostanie zwolniona, gdy tylko wyjdzie poza jego zakres. Innymi słowy, jest to mniej pracy dla Garbage Collectora, a pamięć jest wykorzystywana bardziej wydajnie.
źródło
Użyj klasy, jeśli:
Użyj struktury, jeśli:
źródło
Zawsze używałem struktury, gdy chciałem zgrupować kilka wartości, aby przekazać rzeczy z powrotem z wywołania metody, ale nie będę musiał używać go do niczego po przeczytaniu tych wartości. Tylko jako sposób na utrzymanie porządku w czystości. Zwykle postrzegam rzeczy w strukturze jako „wyrzucane”, a rzeczy w klasie jako bardziej przydatne i „funkcjonalne”
źródło
Jeśli jednostka będzie niezmienna, pytanie, czy użyć struktury czy klasy, będzie na ogół dotyczyło wydajności, a nie semantyki. W systemie 32/64-bitowym odwołania do klas wymagają przechowywania 4/8 bajtów, niezależnie od ilości informacji w klasie; skopiowanie odwołania do klasy będzie wymagało skopiowania 4/8 bajtów. Z drugiej strony każdy wyraźnyinstancja klasy będzie miała 8/16 bajtów narzutu oprócz informacji, które posiada i kosztu pamięci odniesień do niej. Załóżmy, że ktoś chce tablicy 500 jednostek, z których każda zawiera cztery 32-bitowe liczby całkowite. Jeśli jednostka jest typem struktury, tablica będzie wymagać 8 000 bajtów niezależnie od tego, czy wszystkie 500 jednostek jest identycznych, różnych lub pomiędzy nimi. Jeśli jednostka jest typem klasy, tablica 500 referencji zajmie 4000 bajtów. Gdyby wszystkie te odniesienia wskazywały na różne obiekty, obiekty wymagałyby dodatkowych 24 bajtów każdy (12 000 bajtów na wszystkie 500), łącznie 16 000 bajtów - dwa razy więcej niż koszt przechowywania typu strukturalnego. Z drugiej strony kod utworzył jedną instancję obiektu, a następnie skopiował odwołanie do wszystkich 500 gniazd tablic, całkowity koszt wyniósłby 24 bajty dla tej instancji i 4, 000 dla tablicy - łącznie 4024 bajtów. Duże oszczędności. Działałoby niewiele sytuacji, tak jak i ostatnia, ale w niektórych przypadkach może być możliwe skopiowanie niektórych odniesień do wystarczającej liczby gniazd tablic, aby takie współdzielenie było opłacalne.
Jeśli jednostka ma być zmienna, pytanie, czy użyć klasy czy struktury, jest pod pewnymi względami łatwiejsze. Załóżmy, że „Rzecz” jest strukturą lub klasą, która ma pole liczby całkowitej o nazwie x i wykonuje następujący kod:
Czy ktoś chce, aby ta ostatnia instrukcja wpływała na t1.x?
Jeśli Thing jest typem klasy, t1 i t2 będą równoważne, co oznacza, że t1.x i t2.x również będą równoważne. Zatem druga instrukcja wpłynie na t1.x. Jeśli Thing jest typem struktury, t1 i t2 będą różnymi instancjami, co oznacza, że t1.x i t2.x będą odnosić się do różnych liczb całkowitych. Zatem drugie zdanie nie wpłynie na t1.x.
Zmienne struktury i zmienne klasy mają zasadniczo różne zachowania, chociaż .net ma pewne dziwactwa w obsłudze mutacji struktur. Jeśli ktoś chce zachowania typu wartości (co oznacza, że „t2 = t1” skopiuje dane z t1 do t2, pozostawiając t1 i t2 jako odrębne instancje) i jeśli można żyć z dziwactwami w obsłudze typów wartości w .net, użyj struktura. Jeśli ktoś chce semantyki typu wartości, ale dziwactwa .net spowodowałyby popsutą semantykę typu wartości w swojej aplikacji, należy użyć klasy i mamrotać.
źródło
Ponadto doskonałe odpowiedzi powyżej:
Struktury są typami wartości.
Nigdy nie można ich ustawić na Nic .
Ustawienie struktury = Nic, spowoduje ustawienie wszystkich typów wartości na wartości domyślne.
źródło
kiedy tak naprawdę nie potrzebujesz zachowania, ale potrzebujesz więcej struktury niż prosta tablica lub słownik.
Kontynuacja Tak myślę o strukturach w ogóle. Wiem, że mogą mieć metody, ale lubię zachować to ogólne rozróżnienie mentalne.
źródło
Jak powiedział @ Simon, struktury zapewniają semantykę typu „wartość”, więc jeśli potrzebujesz zachowania podobnego do wbudowanego typu danych, użyj struktury. Ponieważ struktury są przekazywane przez kopię, musisz upewnić się, że są małe, około 16 bajtów.
źródło
Jest to stary temat, ale chciałem zapewnić prosty test porównawczy.
Utworzyłem dwa pliki .cs:
i
Uruchom test:
Wyniki:
źródło
Hmm ...
Nie użyłbym śmiecia jako argumentu za / przeciw użyciu struktur vs klas. Zarządzana sterta działa podobnie do stosu - utworzenie obiektu umieszcza ją na szczycie stosu, co jest prawie tak szybkie, jak przydzielanie na stosie. Ponadto, jeśli obiekt jest krótkotrwały i nie przetrwa cyklu GC, dezalokacja jest bezpłatna, ponieważ GC działa tylko z pamięcią, która jest nadal dostępna. (Przeszukaj MSDN, jest seria artykułów na temat zarządzania pamięcią .NET, jestem po prostu zbyt leniwa, by poszukać ich).
Przez większość czasu używam struktury, skończę kopać się za to, ponieważ później odkrywam, że posiadanie referencyjnej semantyki uprościłoby sprawę.
W każdym razie te cztery punkty w opublikowanym powyżej artykule MSDN wydają się dobrą wskazówką.
źródło
class MutableHolder<T> { public T Value; MutableHolder(T value) {Value = value;} }
, a wtedy aMutableHolder<T>
będzie obiektem z modyfikowalną semantyką klas (działa to równie dobrze, jeśliT
jest strukturą lub niezmiennym typem klasy).Struktury znajdują się na stosie, a nie na stosie, dlatego są bezpieczne dla wątków i powinny być używane podczas implementacji wzorca obiektu przenoszenia, nigdy nie chcesz używać obiektów na stosie, są one niestabilne, w tym przypadku chcesz użyć stosu wywołań, jest to podstawowy przypadek użycia struktury Jestem zaskoczony wszystkimi odpowiedziami tutaj,
źródło
Myślę, że najlepszą odpowiedzią jest po prostu użycie struct, gdy potrzebujesz kolekcji właściwości, klasa, gdy jest to zbiór właściwości ORAZ zachowań.
źródło