Okiełznaj Default – Nie Daj Się Zaskoczyć

Aby zrozumieć w pełni czego się spodziewać po FirstOrDefault (lub SingleOrDefault) musisz zrozumieć, czym wyrażenie wartości domyślnych (default) jest.

Default w typach wartościowych

Typy wartościowe w C#: int, long, double, float, byte, char, bool, enumstruktury.

Poniżej kilka przykładów wywołania wyrażenia default. Dla zmiennej typu bool oraz enum jest to również 0, przy czym w przypadku:

  • bool, 0 odpowiada wartości False
  • enum, 0 odpowiada pierwszej wartości tego enuma (domyślny default) lub tej z przypisaną wartością 0
  • char, 0, a dokładniej '\0' (U+0000), „null character”

Default w typach referencyjnych

Typy referencyjne w C#: klasydelegaty, interfejsytablice, zmienne string, czyli elementy rozszerzające klasę System.Object oraz System.String

Poniżej kila przykładów wraz z rezultatami otrzymanymi w konsoli.

Default i typ nullable

Zawsze zwracana jest wartość null. Dla pełnej pewności sprawdzenie poniżej przez is null. Więcej o typach nullable i jak możesz do nich podejść, przeczytasz w tym artykule.

FirstOrDefault() vs SingleOrDefault()

Różnica między First a Single

Obydwie metody (First() oraz Single()) zwracają pojedynczy element z kolekcji. Z tą różnicą, że Single daje zapewnienie istnienia jednego elementu spełniającego warunek, a First zwraca pierwszy element spełniający warunek. W przypadku braku uporządkowania elementów (OrderBy()) zwracane elementy w kolejnych wywołaniach tego samego kodu mogą okazać się losowe.

Or Default – Nie Daj Się Zaskoczyć

Wybierze Pierwszy/Pojedynczy element lub element domyślny.

Przyjrzymy się poniżej pięciu przypadkom i temu co w rezultacie możesz otrzymać.

  1. Istnieje element spełniający warunek m.Number == 1 – rezultat nie ma wartości null
  2. Nie istnieje element spełniający warunek m.Number == 1 = rezultat ma wartość null
  3. Nie istnieje element spełniający warunek m.Number == 1, a dodatkowo wybieramy (Select) konkretne pole typu wartościowego.
    • Rezultat może okazać się niejednoznaczny, wątpliwości rozwiewam w punkcie 5 poniżej.
  4. Nie istnieje element spełniający warunek m.Number == 1, a dodatkowo wybieramy (Select) konkretne pole typu nullable
Odbierz darmowy eBook

5. Powyższy przykład nr 3, wprowadza niepewność, czy dany element nie został znaleziony w kolekcji, czy został i przyjmuje akurat wartość 0 (domyślną dla long). Zakładając że cały obiekt nie jest potrzebny, możesz dokonać boxingu (new {m.Number}) tego jednego elementu i mieć pewność z jakim przypadkiem masz do czynienia.
Szczególnie przydatne przy optymalizacji operacji na IQueryable, gdy chcemy pobierać z bazy tylko te dane które są potrzebne.

Ciekawostka

Operator default możesz wykorzystać jak na poniższym przykładzie, aby utworzyć wartość domyślną typu:

int a = default(int);

Od wersji języka C# 7.1, można użyć samego słowa kluczowego default aby zainicjować zmienną z domyślną wartością:

int a = default;

Default a Swich

Warto dodać, że default jest też wykorzystywany w instrukcji wyboru switch. Przy czym w tej instrukcji definiuje domyślne działanie, a nie reprezentuje wartości, jak np. default(int).

Podsumowanie

Znajomość wartości domyślnych i ich zachowań z pewnością przyda się w programowaniu. Nie daj się zaskoczyć metodom FirstOrDefault/SingleOrDefault i zredukuj czas poświęcony debugowaniu i szukania przyczyn buga / problemu / niechcianego zachowania kodu.

Po więcej ciekawych treści zapraszam do do listy mailowej oraz do strony Programista Jutra na FB.

Subscribe
Powiadom o
guest
0 komentarzy
Inline Feedbacks
View all comments