
C# Tips – Linq i kolekcje
Ile razy pracując na kolekcjach, np. listach musiałeś wybrać z nich tylko te elementy, które spełniały jakiś warunek, albo w prosty sposób chciałeś je posortować? W C# masz dostęp do narzędzia, które na to i wiele więcej pozwoli, w dodatku w prosty i czytelny sposób – mowa o Linq. Jeśli kiedykolwiek miałeś styczność z językiem SQL to zrozumienie Linq nie będzie dla Ciebie problemem. W tym wpisie opiszę tylko używanie Linq z wykorzystaniem metod, inny sposób to pisanie zapytań podobnych do SQL, jednak moim zdaniem są one mniej czytelne przy standardowych zastosowaniach jednak mimo wszystko w późniejszym czasie warto je poznać ponieważ zdarzają się momenty kiedy bez nich się nie obejdziemy. Ale przejdźmy do rzeczy.
W tym wpisie zakładam, że masz jakieś pojęcie o tworzeniu kolekcji i wyrażeniach lambda w C#, ponieważ będę z nich korzystał.
Linq jest domyślnie dołączany do projektu dlatego nie ma potrzeby go w żaden sposób konfigurować. Jedynce co musisz ewentualnie zrobić, to w pliku gdzie go używasz dodać
using System.Linq
I od tej pory masz do niego dostęp bez konieczności podawania pełnej przestrzeni nazw.
Żeby móc pokazać zalety biblioteki trzeba by najpierw podać przykład nie korzystający z niej. Może taki:
var list = new List<User> { new User { FirstName = "Jan", LastName = "Kowalski" }, new User { FirstName = "Tomasz", LasName = "Nowak" }, new User { FirstName = "Jan", LastName = "Nowak" }, new User { FirstName = "Adam", LastName = "Kowalski" } }; foreach(var user in list) { if(user.FirstName == "Jan") { Console.WriteLine(user.LastName); } }
W powyższym przykładzie tworzymy listę użytkowników, do której dodajemy kilka osób. Następnie wypisujemy w konsoli nazwiska wszystkich, którzy mają na imię Jan. Fragment jest prosty jednak jak zwykle wierzę, że czytelnicy są wystarczająco ogarnięci aby wyobrazić sobie bardziej skomplikowany przykład.
Jak pewnie od razu zauważysz, warunek zastosowany w pętli co prawda jest poprawny i ciężko o inny, ale jakoś tak kłuje w oczy. Gdyby zamiast listy była tabela w bazie danych, a zamiast C# SQL to wyciągnięcie tylko tych użytkowników, którzy mają na imię Jan wyglądało by tak:
SELECT * FROM Users WHERE FirstName = 'Jan'
A teraz dobra wiadomość, w Linq operacja będzie wyglądała podobnie! Dokładnie, Linq pozwala np. wyciągać dane w sposób krótki i przyjaźniejszy dla większości programistów, którzy kiedykolwiek mieli kontakt z bazami danych. No więc jak w takim razie będzie wyglądał wcześniejszy przykład z dodanym zapytaniem w Linq? Ano tak:
var list = new List<User> { new User { FirstName = "Jan", LastName = "Kowalski" }, new User { FirstName = "Tomasz", LasName = "Nowak" }, new User { FirstName = "Jan", LastName = "Nowak" }, new User { FirstName = "Adam", LastName = "Kowalski" } }; foreach(var user in list.Where(u => u.FirstName == "Jan")) { Console.WriteLine(user.LastName); }
Gdzie tu Linq? Jest on obecny pod postacią funkcji Where, która przyjmuje jako parametr wyrażenie lambda opisujące warunek. Dzięki temu, że przekazywane jest właśnie całe wyrażenie, możesz swoje warunki budować nie tylko w oparciu o porównywanie wartości, ale też przekazywać element do zewnętrznej funkcji, która po prostu zwróci true/false lub inną wartość, którą znowu porównasz. Pokazana funkcja Where jest jedną z wielu. Inne często używane to:
– First(lambda) – zwracająca pierwszy element, który spełnia warunek podany jako wyrażenie lambda
– FirstOrDefault(lambda) – prawie to samo co wyżej, z tą różnicą, że jeśli żaden element nie spełnia warunku to nie zostanie rzucony wyjątek tylko funkcja zwróci null
– Single(lambda) – podobna do First jednak wymaga aby dokładnie jeden element spełniał warunek. Jeśli takich elementów będzie więcej, albo nie będzie żadnego poleci wyjątek
– SingleOrDefault(lambda) – analogicznie jak przy FirstOrDefault tylko wymaga, żeby warunek spełniał co najwyżej jeden element
– OrderBy(lambda) – sortuje kolekcję rosnąco. Jako parametr przekazywane jest wyrażenie określające wg jakiego pola sortujemy. Przykład sortowania po nazwisku:
var list = users.OrderBy(u => u.LastName);
– OrderBy Descending() – podobna do OrderBy jednak sortuje w kolejności malejącej.
To tylko kilka z funkcji udostępnianych przez Linq. Jednak mając IntelliSense w Visual Studio, jak również przeglądając strony Microsoftu na pewno łatwo odnajdziesz kolejne, tym bardziej, że nazwy są często trafne i dobrze informują o działaniu poszczególnych metod.
Jeszcze jedną ważną, jak nie najważniejszą cechą Linq jest możliwość „łańcuchowego” wywoływania pokazanych przed chwilą funkcji, co jeszcze bardziej upodabnia je do SQLowych zapytań. Dzięki temu w jednym zapytaniu możesz wykonać kilka operacji. Przykładowo chcąc wybrać użytkowników o imieniu Jan i posortować ich alfabetycznie wg nazwiska może to zrobić tak:
var list = users.Where(u => u.FirstName == "Jan").OrderBy(u => u.LastName);
Kiedy zaczniesz na co dzień korzystać z Linq po pewnym czasie nie będziesz potrafił się bez niego obejść. Prostota i przejrzystość w typowych zastosowaniach sprawiają, że jest to, moim zdaniem, jedna z najlepszych funkcjonalności dodanych do frameworka .NET.
Leave a Comment