Struktury - kiedy, gdzie i dlaczego?

0

Nigdy się nie zagłębiałem w temat, myślałem że struktury istnieją dla kompatybilności np z kodem C/C++, no ale po przeczytaniu pewnego artykuły zacząłem je gdzieniegdzie dostrzegać np chyba klasa Point w WinForms jest strukturą.
Rozumiem konstrukcję, jednak nie potrafię wyciągnąć zalet i kiedy taktownie mógłbym je stosować.

Jeżeli je wykorzystujecie to w jakich okolicznościach i dlaczego?

1

Główna różnica w stosunku do klasy to fakt, że struktura jest typem wartościowym więc wszędzie przekazywana jest przez wartość, a co za tym idzie jest kopiowana. Sam w zasadzie zawsze korzystam z klas, a jeżeli naprawdę korzystam z jakiejś struktury to zwykle jest ona częścią frameworku albo jakiejś biblioteki więc jej umieszczenie tam jest raczej dobrze przemyślane np. DateTime.

Generalnie warto pogoglować hasło: c# struct vs class
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct
https://stackoverflow.com/questions/13049/whats-the-difference-between-struct-and-class-in-net

0

Od siebie dodam, że jeżeli piszesz nową strukturę to powinna być immutable. Struktury dają kilka zalet nad klasami, pod warunkiem, że są napisane dobrze. Struktura to typ wartościowy i w pamięci jest alokowany na stosie co może być małą pomocą dla Garbage Collectora przy dużej ilości obiektów.

Jeśli pójdziemy śladem tego, że dobrze napisana struktura jest immutable to jest to idealny klucz do słowników i hash tables. Obiekt, który jest immutable będzie też thread-safe.

2

@biały Szewc mała poprawka: struktura jest alokowana tam gdzie została stworzona. Jeżeli struktura jest polem/właściwością klasy to zostanie zalokowana na stercie. Dodatkowo struktura może być przekazywana również przez referencję, więc czasami można się pozbyć kosztów kopiowania, jednak kod z dużą ilością ref parameters może być niebezpieczny.

0

Czyli w takim spontanicznym programowaniu nie ma co ich dotykać.

0

Najlepiej w ogóle nie zajmować się "spontanicznym programowaniem".

3

Czym różni się struktura od klasy?
Każdy Ci powie, że struktura jest typem wartościowym, a klasa referencyjnym. I co z tego wynika? Że struktury są przekazywane przez parametry tak jak int, double, czy byte. Przekazywana jest ich kopia:


void Foo(int a)
{
  a += 5;
}
void Main()
{
  int i = 5;
  Foo(i);
}

Po tym kodzie zmienna i cały czas będzie miała wartość 5. Do metody Foo została przekazana jakaś tymczasowa kopia tej zmiennej. Ale możemy też ją przekazać przez referencję:

void Foo(ref int a)
{
  a += 5;
}
void Main()
{
  int i = 5;
  Foo(ref i);
}

Po tym kodzie, zmienna i będzie miała wartość 10, ponieważ została przekazana przez referencję. Czyli w pewnym sensie przez wskaźnik. Tutaj w metodzie Foo operujesz bezpośrednio na zmiennej i, a nie na jej kopii.

I teraz domyślnym zachowaniem dla klas (typów referencyjnych) jest przekazywanie ich do metod przez referencję. Domyślnym zachowaniem dla typów wartościowych jest przekazywanie ich do metod za pomocą kopii. A skoro struktura jest typem wartościowym, to zostanie przekazana jej kopia.

Kiedy używać struktur
Wtedy, gdy struktura reprezentuje coś w rodzaju typu liczbowego. Nie wiem, jak to wyjaśnić lepiej, więc przykład.
Liczba zespolona. Składa się z części rzeczywistej i urojonej. A więc ma jakby dwa składniki. Nie przedstawisz liczby zespolonej jako inta, więc musisz zrobić z tego strukturę:

struct Complex
{
  public int Real { get; }
  public int Imaginary { get; }
}

Różnica jest jeszcze taka, że struktury mają być immutable. Czyli nie możesz zmienić raz utworzonej struktury. Za każdym razem musisz ją tworzyć na nowo:

Complex c = new Complex(1, 2);

To jest jedyny możliwy sposób zmiany struktury.

Innym przykładem na zastosowanie struktury jest np. Punkt. To też jest kilka składowych, które tworzą pewną całość.

Także struktur używaj w prostych przypadkach, w których reprezentują one coś w rodzaju jednej "liczby" (nie umiem tego lepiej wyjaśnić :)) - liczba zespolona, punkt, data (dzień / miesiąc / rok) itd.

Wszędzie indziej używaj klas.

0

Ale się kolego napracowałeś... Doceniam.

A np gdy tworzę obiekt i przyjmuję inne obiekty w konstruktorze, to tworzę ich nową kopię żeby zgubić referencję(no bo obiekty immutable są niewygodne zazwyczaj) i w takich wypadkach mógłbym użyć struktur? No bo wtedy jest auto kopia i po problemie. I akurat modele to u mnie są zwykłe pojemniki na dane bez operacji, więc chyba się nadaje. Chyba że jakiś fakt pominąłem.

0

Tak, chociażby to, żeby nie używać struktur do instancji, które mają mieć więcej niż 16 bajtów.
Pomyśl jaka będzie wydajność kopiowania takich dużych obiektów.

Jaki właściwie problem chcesz rozwiązać tym kopiowaniem?

0

Ano ta, bo przecież jakbym chciał zinstancjonować strukturę to ona znów sie skopiuje. No fakt.
A chodziło mi to, żeby nie musieć ręcznie kopiować albo tworzyć oddzielnej defenicji dla immutable bo czasem tak robie.
No cóż. Fajnie że jest forum i może podyskutować : D

0

Nie rozumiem. Po co chcesz kopiować obiekt immutable? Ani to praktyczne, ani wydajne.

0

Mutable do immutable.
Często tworze dwie definicje bo jakoś tak czuję wewnątrzą potrzebę.

0

imo poza frameworkiem struktury powinny byc traktowane jak kod unsafe - niedostepne dopoki ktos ich explicite nie wlaczy.
niepotrzebnie komplikuja jezyk bo maja pare znaczacych roznic i pulapek w stosunku do klas a dla 99.99% use casow ktore widzialam byly uzyte blednie lub niepotrzebnie.
pare typowych zastosowan:

  1. native/interop/etc - tutaj nie ma wyjscia, ale ich uzycie powinno byc enkapsulowane tak zeby "normalny" kod juz operowal na klasach
  2. typy reprezentujace jakas "wartosc" np. liczbe, date czy indeks (np. tworcy frameworka pomysleli ze bedzie spoko zrobic Enumerator jako strukture... https://msdn.microsoft.com/en-us/library/x854yt9s(v=vs.110).aspx) a ty daj sobie spokoj, nic nie zyskujesz, a mozesz napotkac problemy jak przyjdzie tego uzywac albo rozbudowac
  3. WYDAJNOSC - bzdura, jak ktos tlumaczy ze zrobil cos struktura zeby oszczedzac cykle cpu to zwyczajnie sciemnia (albo nie wie o czym gada). jesli chodzi o zuzycie pamieci to jesli ladujesz az tak duzo danych do ramu ze class vs struct robi roznice to znaczy ze masz skopana architekture i jesli zamienisz na struktury to chyba tylko po to zeby zarobic troche xpekow w profilowaniu (bo jesli w ogole to pomoze to jedynie doraznie, powodujac przy okazji pare powazniejszych problemow).

btw przyklad z zycia, w jednym projekcie ktos wspanialomyslnie stworzyl immutable struct do trzymania 128 intow i operacjach na nich, spedzil mase czasu na dopieszczaniu jej i optymalizacji przypadkow uzycia tak zeby bylo jak najmniej kopiowania, mimo wszystko - w pewnym momencie zamienilismy to na klase co dalo skok wydajnosci + bardzo ulatwilo prace bo tak naprawde wystarczyla jedna prosta konwencja zamiast koniecznosci zagladania do obszernej dokumentacji struktury Int128 co drugi dzien ;)

reasumujac - nie uzywaj struktur. jesli nie wiesz czy ich uzyc w danym przypadku to znaczy ze nie powinienes ich uzywac.
ale naucz sie tych wszystkich bzdetow o stosie i stercie, konstruktorach, dziedziczeniu, rzutowaniu itp dla klas vs struktur bo na rozmowach o to pytaja :)

0

Ale Ty masz doświadzenie... Z Twoich wypowiedzi widać że zęby na tej profesji zjadłaś : D

Ja w sumie pisząc w C# cały czas je miałem za unsafe, tylko taka jakaś głębsza refelksja mnie naszła, bo próbuje się jakoś rozwinąć trochę w sztuce programowania i tak kombinuję.

Dzięki wszystkim co się udzielali.

0
katelx napisał(a):
  1. WYDAJNOSC - bzdura, jak ktos tlumaczy ze zrobil cos struktura zeby oszczedzac cykle cpu to zwyczajnie sciemnia (albo nie wie o czym gada). jesli chodzi o zuzycie pamieci to jesli ladujesz az tak duzo danych do ramu ze class vs struct robi roznice to znaczy ze masz skopana architekture i jesli zamienisz na struktury to chyba tylko po to zeby zarobic troche xpekow w profilowaniu (bo jesli w ogole to pomoze to jedynie doraznie, powodujac przy okazji pare powazniejszych problemow).

Akurat wydajność to może być dobry argument za użyciem struktur, tylko tego nie robi się w crudach, ale np. w silnikach baz danych.

1 użytkowników online, w tym zalogowanych: 0, gości: 1