Blog Dla Młodszych Programistów C#/.NET

Dzisiejszy wpis pojawia się trochę później niż zazwyczaj, ale oczywiście nie mogło go zabraknąć. Wynika to przede wszystkim z tego, że miałem dzisiaj więcej pracy niż zwykle, ponadto w końcu wystartowałem z moim kanałem na youtube, do którego przygotowywałem się już dość długo. Na kanale będę chciał dzielić się swoją wiedzą programistyczną, także również zapraszam Cię w to miejsce (kanał youtube). Dzisiejszy artykuł chciałem poświęcić 4 wyrażeniom, które na pewno zdarzyło Ci się już nie raz użyć, pisząc zapytania za pomocą LINQ. Mówię tutaj o First, FirstOrDefault, Single oraz SingleOrDefault. Przyznaj się, czy tak naprawdę wiesz w jakich sytuacjach, które z tych wyrażeń powinno się użyć? Czy raczej ciągle używasz tego samego w każdej sytuacji? W tym artykule poznasz dokładnie jakie są między nimi różnice i w jakich sytuacjach najlepiej je używać.

Czy Tak Naprawdę Znasz Różnice Pomiędzy First vs FirstOrDefault vs Single vs SingleOrDefault?


Przykład


Przygotowałem prostą listę, na której będziemy testować te wyrażenia:
var numbers = new List<int> { 12, 42, 1, 10, 12 };
Sprawdzimy 2 różne scenariusze dla każdego wyrażenia. Interesują nas takie przypadki:
1) Pobieranie wartości z listy, gdy kilka liczb spełnia warunek.
2) Pobieranie wartości z listy, gdy szukana liczba nie istnieje w tej liście.


First()


var firstValueWhen2Match = numbers.First(x => x == 12);
Console.WriteLine(firstValueWhen2Match);//12
var firstValueWhenDoesntExists = numbers.First(x => x == 0); //System.InvalidOperationException
Console.WriteLine(firstValueWhenDoesntExists);
1) Jeżeli jest więcej wartości spełniających warunek, to gdy użyjesz First(), to zostanie zwrócona tylko pierwsza z nich i to kończy dalsze przeszukiwanie listy.
2) Jeżeli First() nie znajdzie żadnej wartości, która spełnia warunek, to zostanie rzucony wyjątek System.InvalidOperationExeption.


FirstOrDefault()


var firstOrDefaultValueWhen2Match = numbers.FirstOrDefault(x => x == 12);
Console.WriteLine(firstOrDefaultValueWhen2Match);//12
var firstOrDefaultValueWhenDoesntExists = numbers.FirstOrDefault(x => x == 0);
Console.WriteLine(firstOrDefaultValueWhenDoesntExists);//0
1) Jeżeli jest więcej wartości spełniających warunek, to gdy użyjesz FirstOrDefault(), to zostanie zwrócona tylko pierwsza z nich i to kończy dalsze przeszukiwanie.
2) Jeżeli FirstOrDefault() nie znajdzie żadnej wartości, która spełnia warunek, to zostanie zwrócona domyślna wartość, w tym przypadku 0.


Single()


var singleValueWhen2Match = numbers.Single(x => x == 12);//System.InvalidOperationException
Console.WriteLine(singleValueWhen2Match);
var singleValueWhenDoesntExists = numbers.Single(x => x == 0);//System.InvalidOperationException
Console.WriteLine(singleValueWhenDoesntExists);
1) Jeżeli jest więcej wartości spełniających warunek, to przy użyciu Single() zostanie rzucony wyjątek System.InvalidOperationExeption.
2) Jeżeli Single() nie znajdzie żadnej wartości, która spełnia warunek, to zostanie rzucony wyjątek System.InvalidOperationExeption.


SingleOrDefault()


var singleOrDefaultValueWhen2Match = numbers.SingleOrDefault(x => x == 12);//System.InvalidOperationException
Console.WriteLine(singleOrDefaultValueWhen2Match);
var singleOrDefaultValueWhenDoesntExists = numbers.SingleOrDefault(x => x == 0);
Console.WriteLine(singleOrDefaultValueWhenDoesntExists);//0
1) Jeżeli jest więcej wartości spełniających warunek, to przy użyciu SingleOrDefault() zostanie rzucony wyjątek System.InvalidOperationExeption.
2) Jeżeli SingleOrDefault () nie znajdzie żadnej wartości, która spełnia warunek, to zostanie zwrócona domyślna wartość, w tym przypadku 0.


W jakich sytuacjach stosować jakie wyrażenia?


1) Jeżeli wiesz, że powinien być tylko jeden rekord (single) spełniający dany warunek i nie może być więcej niż jeden, to wtedy powinieneś użyć Single() lub SingleOrDefault() - w zależności od tego, czy oczekujesz wyjątku, czy wartości domyślnej, gdy nie będzie rekordu spełniającego warunek.
2) Jeżeli interesuje Cię tylko pierwszy rekord (first) spełniający warunek i nie ma dla Ciebie znaczenie, że może być więcej rekordów spełniających ten warunek, to powinieneś użyć First() lub FirstOrDefault() - w zależności od tego, czy oczekujesz wyjątku, czy wartości domyślnej, gdy nie będzie rekordu spełniającego warunek.
3) Pamiętaj też o tym, że wyrażenie First() i FirstOrDefault() jest szybsze niż Single() i SingleOrDefault(), ponieważ już po znalezieniu pierwszej szukanej wartości, dalsze przeszukiwanie kolekcji jest zakończone.


PODSUMOWANIE


W tym krótkim, ale bardzo ważnym artykule przedstawiłem Ci podstawowe różnice pomiędzy 4 popularnymi wyrażeniami z LINQ. Pamiętaj, że nie do każdej sytuacji nadają się wszystkie z nich. Staraj się wybierać odpowiednie wyrażenia w zależności od sytuacji. Również pamiętaj o tym, że rekruterzy często pytają na rozmowach kwalifikacyjnych o podstawowe różnice pomiędzy tymi wyrażeniami, dlatego mam nadzieję, że nie dasz się już zaskoczyć takim pytaniem 🙂

Poprzedni artykuł - Różnica Pomiędzy ViewData, ViewBag oraz TempData.
Następny artykuł - Ref vs Out Na Przykładach w C#
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Specjalizuje się w ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Komentarze (2)
zefirski
ZEFIRSKI, 28 grudnia 2020 18:19
Super artykuł, szukałem tego, bardzo dużo mi wyjaśnił
Marek
MAREK, 11 stycznia 2021 03:42
Rzeczywiście mogę potwierdzić, że pytają o różnice. Ostatnio na rozmowie dostałem takie właśnie, precyzyjne pytanie.
Dodaj komentarz

Wyszukiwarka

© Copyright 2021 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Polityka prywatności. Design by Kazimierz Szpin