StrukturaCzęść NR.8 Klasy są typami referencyjnymi i ich zawartość jest zawsze tworzona na stercie. W niektórych wypadkach klasa zawiera tak niewielką ilość danych , że zarządzanie nimi na stercie jest nieopłacalne. W takich wypadkach lepiej użyć struktury.

Struktura jest typem wartościowym, czyli jej miejsce jest na stosie.

Chociaż jeśli struktura jest duża to lepiej stosować klasy.

Dla programistów C++
W C++ struktura to odpowiednik klasy, tylko jej składowe są publiczne (w klasie prywatne). W C# struktury to typ skalarny i podstawowe różnicę pomiędzy klasą i strukturą zostały opisane we wpisie

Podobnie jak klasy struktura może mieć własne pola i metody……oraz w pewnym specjalnym wypadku konstruktor.

Przykładem struktury jest np. Point w WPF i Windows Forms, która przechowuje dwie zmienne X i Y.

Point struktura
Jednak co ważniejsze i możesz nie zdawać sobie z tego sprawy, ale strukturami są też podstawowe typy numeryczne, jak np. int , który tak naprawdę jest strukturą System.Int64. Te struktury mają metody jak np. ToString() czy stałe (const) jak wartość maksymalna i minimalna dla int, czy dla float nieskończoność.

float struktura
Oto mała tabelka wyjaśniająca, co jest strukturą , a co klasą

Słowo kluczoweAlias doCzym to jest?
boolSystem.BooleanStruktura
byteSystem.ByteStruktura
decimalSystem.DecimalStruktura
doubleSystem.DoubleStruktura
floatSystem.SingleStruktura
intSystem.Int32Struktura
longSystem.Int64Struktura
sbyteSystem.SByteStruktura
shortSystem.Int16Struktura
uintSystem.UInt32Struktura
ulongSystem.UInt64Struktura
ushortSystem.UInt16Struktura
objectSystem.ObjectKlasa
stringSystem.StringKlasa


Podstawową różnicą pomiędzy strukturą i klasą jest to, że struktury nie obsługują dziedziczenia.
Tak czy siak, oczywiście możemy tworzyć swoje własne struktury.

Tworzenie struktury

Aby zadeklarować strukturę analogicznie do klasy używasz słowa kluczowego struct. Analogicznie do klasy zawartość naszej struktury zawiera się pomiędzy nawiasami klamrowymi.

struct Punkt3D 
{
    public double X;
    public double Y;
    public double Z;
}
Oto prosta struktura “Punkt3D”. Dużo jej brakuje do tego, by mogła być używana , ale o tym na końcu wypisu.

Struktura może posiadać konstruktor pod warunkiem , że zawiera on jakieś parametry. Mówiąc prościej nie można stworzyć domyślnego konstruktora w strukturze.
struct Punkt3D 
{
    public Punkt3D(double x, double y, double z)
    {
        X = x; Y = y; Z = z;
    }
    public double X;
    public double Y;
    public double Z;
}
Powód, dla którego nie możesz zadeklarować konstruktora bezparametrowego jest dosyć prosty.

Kompilator zawsze za ciebie go tworzy. W klasie, jeśli nie napiszesz domyślnego konstruktora kompilator go stworzy, a konstruktor wypełni wszystkie pola w klasie domyślnymi wartościami (int =0,bool = false).

Struktora bład konstruktor
Dla domyślnego konstruktora, którego nie możemy stworzyć, wartości stworzone przez niego w strukturze zawsze będą domyślne.

Ważna uwaga co do konstruktorów z parametrami. Dla struktur muszą one uzupełniać wszystkie pola jakimiś wartościami. W tym wypadku wartość “z” nie ma żadnej przypisanej wartości i uzyskałem błąd kompilacji.

Struktura wartość wszystkie
Dla dużej ilości pól ten problem może być rozwiązany za pomocą dziedziczenia konstruktorów. Dziedzicząc po konstruktorze domyślnym wartość “Z” będzie ustawiana według niego, czyli na wartość domyślną dla int zero.
public Punkt3D(double x,double y) :this()
{
    X = x; Y = y; 
}

Wybacz , że nagle mówię o dziedziczeniu i o słowie kluczowym this , o którym jeszcze nic nie wspomniałem, ale lepiej zapamiętać taką sztuczkę.

W strukturze nie możesz inicjować domyślnych wartości dla pól przeciwieństwie do klas.

struktura incjalizacja pola
Oto tabelka podsumowująca różnicę pomiędzy klasą a strukturą.

PytanieStrukturaKlasa
Typ wartościowy czy referencyjny?Typ wartościowyTyp referencyjny
Jej instancja żyje na stosie czy na stercieNa stosie i są wartościami.Na stercie i są nazywane obiektami.
Można w niej napisać domyślny konstruktorNieTak
Kiedy napiszesz swój konstruktor, czy kompilator wciąż stworzy swój domyślny.TakNie
Jeśli nie zainicjujesz pól w swoim własnym konstruktorze, czy kompilator automatycznie za ciebie je zainicjuje.NieTak
Czy możesz przypisać wartości do pól w momencie deklaracji?NieTak


Użycie struktury nie powinno być dla ciebie niczym nowym.

Punkt3D p1 = new Punkt3D(1, 2, 3);

Możesz się zastanawiać, dlaczego używamy słowa kluczowego new. Słowo kluczowe new wywołuje konstruktor. Konstruktor, który wypełnia pola. Jednak struktura to typ wartościowy więc powinien dać się używać również bez słowa kluczowego new.

Punkt3D p2;
p2.X = 2;
p2.Y = 3;
p2.Z = 5;

Można używać struktur bez słowa kluczowego new, ale nie jest to zalecane i prowadzi do niepotrzebnego zamieszania. Zalet z takiego rozwiązania prawie nie ma. Trzeba tylko przypisać do wszystkich pól w strukturze wartości, tak jakby zrobił to konstruktor , aby używać jej w pełni poprawnie.

Struktura też może być rozszerzona o typ nullable , aby dać jej możliwość przechowywania braku wartości.

Punkt3D? p1 = null;

Jak działa struktura na stosie. Zobrazowanie

Co się dzieje, gdy napiszę strukturę bez użycia jej konstruktora.

klass typy referencyjne-08

Jak widzisz wartości nie są zainicjowane. Jest to możliwe, ale niektóre funkcje struktury mogą wywołać błąd, ponieważ jej pola nie mają przypisanych wartości.

Oto co się dzieje, gdy użyjemy słowa kluczowego new i wywołamy domyślny konstruktor dla struktury.
klass typy referencyjne-10

Wszystkie pola w strukturze mają teraz domyślne wartości. Myślę ,że wiesz co się wydarzy gdy uruchomię mój konstruktor.
klass typy referencyjne-09

To wszystko. Nie bardzo, czego jeszcze brakuje?

Domyślnie struktury nie mają wbudowanych zachowań dla poszczególnych operatorów. Czyli na chwilę obecną nie mamy możliwości dodawania, odejmowania czy porównywania własnych struktur.

struktury
Ma to sens w końcu co byśmy otrzymali dodając dwa punkt w przestrzeni 3D. Powinniśmy może dodawać do punktów 3D tylko odpowiednie wektory. Jednym słowem domyślne wbudowane zachowania jak dodanie jednej wartości do drugiej zrobiłoby tylko nieodpowiednie zamieszanie.

Oczywiście możesz stworzyć swoją implementację dla poszczególnych operacji ,ale o tym kiedy indziej.