EmptyCzęść NR.4 W tej części kursu zostanie omówiona wartość "null" oraz specjalne zmienne wartościowe, które tę wartość mogą przechowywać.

Odwołanie się do pustej referencji skutkuje znanym wyjątkiem “NullReferenceException”.

Puste referencje

Kiedy deklarujesz zmienną, dobrym pomysłem jest od razu ją zainicjować. Klasa w podobnym stylu musi przechowywać jakąś referencję do obiektu. Na razie skoncentrujemy się na pustych referencjach.

Ale w programowaniu występują pewne sytuacje, w których wypada sprawdzić czy dana zmienna przechowują jakąś referencję. Może nie wykonał się jakiś fragment kodu, który stworzyłby dany obiekt i warto byłoby przechwycić bądź sprawdzić czy nasza klasowa zmienna nie jest pusta.

Np. chcemy wykonać jakąś operację dla typu łańcuchowego , a może okazać się on pusty. W takim wypadku istnieje duża szansa na zobaczenie wyjątku “NullReferenceException”. Dla przypomnienia string jest typem referencyjnym. Może się też zdarzyć , że dana metoda otrzyma pustą referencję.

Wyjtek-null-reference_thumb2
Z drugiej strony może z jakiegoś powodu chcesz , aby zmienna przechowywała pustą referencje. Oto przykład. Do przechowywania pustych referencji służy słowo kluczowe null.

Cuboid cu3 = null;
//......kod który wykona się więcej niż raz

if (cu3 == null)
{
    cu3 = new Cuboid(2, 3, 6);
    cu3.Volume();
}
else
{
    cu3.Volume();
}

Warto tutaj zaznaczyć , że ciągle mówi się tutaj o pustych referencjach , a nie o pustych obiektach.Nie ma czegoś takiego jak puste obiekty.Zmieszanie To błędne myślenie wynika właśnie z braku znajomości podstaw.

W C# możesz przypisać wartość null do jakiegokolwiek typu referencyjnego. Wartość null będzie znaczyła, że zmienna nie referuje się do żadnego obiektu przechowywanego w pamięci.

Puste wartości i typy nullable

Wartość null jest znakiem tego , że dana zmienna nie przechowuje referencji. Czyli wartość null nie może być przypisana do typu wartościowego, ponieważ null nie jest reprezentacją wartości.

nie-legalny-zapis-null_thumb2
W C# istnieje jednak modyfikator, który pozwala na tworzenie zmiennych z wartością null . Te zmienne zachowują się w podobny sposób do oryginalnych typów, z tym że można do nich przypisać wartość null.

Warto zaznaczyć ,że ten specjalne typy wartościowe wciąż są typami wartościowymi. To ,że nagle do typów wartościowym możemy przypisać null nie znaczy ,że magicznie on stał się typem referencyjnym. Tak naprawdę dzieje się tutaj dużo magii kompilatora, której nie widzimy.

Zmienne te deklaruje się za pomocą znaku zapytania, który powinien być napisany zaraz po typie bez spacji.

bool? b = null;
int? bb = null;
float? bbb = null;

Teraz możesz sprawdzać, czy dana zmienna ma wartość, czy nie.

if (b == null)
    b = true;

Jednak z typem nullable istnieje pewien mały problemy. Można przypisać co prawda wartość z typu int na int? , ale operacja w drugą stronę jest niewykonalna. Ponieważ typ int nie jest w stanie obsłużyć wszystkich wartości z int?. W takim wypadku pozostaje rzutowanie.

int-nullable-do-int._thumb2
Wartość “i” nie może zawierać w sobie wartości null , natomiast “j” może zawierać wszystkie wartości zwykłego int-a z dodatkową wartością null.

Kolejną zaletą typów nullable (nie ma tutaj polskiego odpowiednika tego słowa) jest fakt , że posiadają pewne dodatkowe właściwości.

HAS-Value-Nullable-types_thumb4 


Właściwością “HasValue” możesz sprawdzić, czy wartość nie jest pusta.

 

if (!b.HasValue)
    b = true;

Możesz też sprawdzić wartość za pomocą właściwości “Value” (jest ona tylko do odczytu). Są one przydatne przy bardziej złożonych zmiennych jak struktury i typy wyliczeniowe. One oczywiście też zostaną omówione.