1. Giriş
Təsəvvür elə, kitabxanaya gəlmisən və sənə proqramlaşdırma ilə bağlı bütün kitabları tapmaq lazımdır, amma yalnız 2020-ci ildən sonra nəşr olunanları və müəllif adına görə sıralanmış şəkildə. Yəqin ki, hər rəfə qaçıb, hər kitabı əl ilə yoxlamazdın, düzdür? Sən kitabxanaçıdan kömək istəyərdin, çünki o, lazım olanı tez tapmağı bacarır.
LINQ (Language Integrated Query, yəni "Dilə inteqrasiya olunmuş sorğular") — bizim "ağıllı kitabxanaçımızdır", "SQL-motorumuzdur" (yəni, məlumatlara sorğu yazmaq üçün alət) birbaşa C#-ın içində!
LINQ-a belə bax: sən nə istədiyini necə yox, nə istədiyini təsvir edirsən. Yəni, "Birinci elementi götür, şərti yoxla, uyğundursa yeni siyahıya əlavə elə, sonra ikinciyə keç..." demək əvəzinə, sadəcə deyirsən: "Mənə qiyməti 1000-dən yuxarı olan bütün məhsulları ver." Qalanını C# özü ən effektiv şəkildə həll edir.
LINQ-un əsas ideyası: IEnumerable<T> interfeysini reallaşdıran istənilən məlumat mənbəyinə standart sorğu sintaksisi verməkdir. Bu superdir, çünki List<T>, massivlər, HashSet<T> — bunların hamısı IEnumerable<T>-i dəstəkləyir. Əgər məlumatların bazadadırsa, xüsusi kitabxanalar (məsələn, Entity Framework) sənin LINQ-sorğunu əsl SQL-ə çevirəcək!
LINQ C#-da artıq 10 ildən çoxdur ki, var. Bu, .NET-də məlumatlarla işləməyə yanaşmanı dəyişən əlamətdar hadisə idi. LINQ-dan əvvəl, kolleksiyaları filtrləmək, sıralamaq və çevirmək üçün çoxlu şablon kod yazmaq lazım idi. Və ya SQL-sorğularını sətir kimi yazırdın, amma onlar kompilyator tərəfindən yoxlanmırdı və run-time-da səhvlərə səbəb olurdu. LINQ "sorğu" konsepsiyasını birbaşa proqramlaşdırma dilinə gətirdi, onları tip-təhlükəsiz və daha oxunaqlı etdi.
Çoxları hesab edir ki, LINQ — C#-da Generics çıxdıqdan bəri ən böyük yeniliklərdən biridir.
2. LINQ-un üstünlükləri: Niyə hamı onu sevir?
Kodun qısa və oxunaqlı olması: Məsələn, böyük bazada qiyməti 1000-dən yuxarı olan məhsulları filtrləmək üçün əvvəllər bir neçə sətr kod yazmaq lazım idi. LINQ ilə bunu bir sətrdə edə bilərsən. Az kod — az potensial səhv, daha çox oxunaqlılıq və anlaşıqlılıq. Kod daha təbii dilə yaxın olur.
Proqramçı zarafatı: "Nə qədər az kod yazıram, bir o qədər az bug əlavə edə bilərəm." LINQ bu işdə köməkçindir!
Güclü və çevik: LINQ çoxlu əməliyyatlar təklif edir: filtrasiya (Where), proyeksiya (Select), sıralama (OrderBy), qruplaşdırma (GroupBy), aqreqasiya (Sum, Average), birləşdirmə (Join) və s. Bu əməliyyatları birləşdirərək mürəkkəb məlumat emalı məsələlərini həll edə bilərsən.
Tip-təhlükəsizlik: Bu çox vacibdir! SQL-sorğunu sətir kimi yazanda, kompilyator heç nə bilmir. Sütunun adında səhv etsən, proqram yalnız işləyərkən səhv verəcək. LINQ ilə isə C# kompilyatoru sənin sorğunu dərhal yoxlayır. Product obyektində olmayan sahəni soruşsan, kompilyator dərhal səhv göstərəcək. Sanki şəxsi korrektorum var, səhvlərini başqaları görməmişdən qabaq tutur.
Dilə inteqrasiya: LINQ-sorğular — hansısa "sehrli" sətirlər deyil. Bunlar tam C# konstruksiyalarıdır, tanış lambda ifadələrindən və tanış məlumat tiplərindən istifadə edir. Bu, LINQ-a keçidi çox rahat edir.
Gecikdirilmiş icra (Deferred Execution): Bu LINQ-un ən cool və bəlkə də ən çətin anlayışlarından biridir, amma çox vacibdir. Məsələ ondadır ki, LINQ-sorğu elə yazan kimi icra olunmur. O "yığılır" və sən həqiqətən nəticə istəyəndə (məsələn, foreach ilə dövrə başlayanda) işləyir. Bu, xüsusilə böyük məlumatlarla işləyəndə sorğuları optimallaşdırmağa imkan verir. Bu barədə daha ətraflı 166-cı mühazirədə danışacağıq. Hələlik sadəcə yadında saxla: LINQ ağıllıdır, artıq iş görmür.
Universallıq və genişlənəbilənlik: LINQ — təkcə yaddaşdakı siyahılar üçün deyil. Müxtəlif LINQ "provider"ləri var:
- LINQ to Objects: yaddaşdakı kolleksiyalar üçün (List<T>, massivlər və s.).
- LINQ to SQL / Entity Framework Core: SQL verilənlər bazası üçün (sənin LINQ-sorğuların SQL-sorğulara çevrilir).
- LINQ to XML: XML sənədlərlə işləmək üçün.
- Və bir çox başqaları.
Bu o deməkdir ki, LINQ-u öyrəndikdən sonra müxtəlif mənbələrdən olan məlumatlarla eyni sorğu məntiqi ilə işləyə biləcəksən.
3. Kolleksiyalarla "köhnə üsulla" işləməyin problemi
LINQ-dan əvvəl C#-da kolleksiyalarla işləyən kod təxminən belə idi:
var products = new List<Product> { /* ... */ };
var expensive = new List<Product>();
foreach (var prod in products)
{
if (prod.Price > 100)
expensive.Add(prod);
}
expensive.Sort((a, b) => a.Price.CompareTo(b.Price));
foreach (var item in expensive)
Console.WriteLine(item.Name);
Bu yanaşma tipikdir: əvvəlcə əl ilə filtrlə, sonra sırala — mütləq aralıq siyahı yarat. Məntiq nə qədər çoxdursa, kod, səhv və dəyişən də bir o qədər çox olur. Bütün bunlar mebel yığma sexini xatırladır: detallar var, amma yığmaq — əl işidir və yorucudur.
Dövrələr ölkəsində Alisa
Təsəvvür elə, səndə böyük bir istifadəçi siyahısı var və sən yalnız 18-dən böyük olan və Neonvil şəhərində yaşayanların adlarını, əlifba sırası ilə sıralanmış və ilk üçünü çıxarmaq istəyirsən. Sənə iç-içə dövrlər, şərtlər, sıralamalar, köməkçi siyahılar yazmaq lazım olacaq... və ya sadəcə LINQ istifadə edə bilərsən.
4. LINQ-sorğusu necə görünür? Sadə nümunələr
LINQ-un iki əsas sintaksisi var:
- Method Syntax (metod-zənciri)
- Query Syntax (SQL-ə bənzər dil)
Ən çox Method Syntax istifadə olunur, xüsusilə müasir layihələrdə. Bizim tətbiq nümunəsində belədir:
var expensive = products
.Where(p => p.Price > 100)
.OrderBy(p => p.Price)
.Select(p => p.Name)
.Take(3);
foreach (var name in expensive)
Console.WriteLine(name);
Hər şey aydındır: filtr, sıralama, konkret sahənin seçilməsi, sayın məhdudlaşdırılması. Minimum kod — maksimum məna.
Eyni şey Query Syntax ilə
var expensive = from p in products
where p.Price > 100
orderby p.Price
select p.Name;
foreach (var name in expensive.Take(3))
Console.WriteLine(name);
Hər iki variant eyni nəticəni verir — hansını xoşlayırsansa onu seç (amma method-sintaksis daha çox istifadə olunur).
5. LINQ-un arxitekturası: qapağın altında nə var?
LINQ istənilən kolleksiya ilə işləyir, əsas odur ki, IEnumerable<T> (və ya IQueryable<T>, bu barədə sonra danışacağıq) interfeysini dəstəkləsin.
LINQ-un əsas komponentləri
| Komponent | Qısa təsvir |
|---|---|
| LINQ extension-klassları | Statik metodlar (, , və s.) sinfində |
| Delegatlar | Ən çox və istifadə olunur |
| Gecikdirilmiş icra | Sorğu yalnız ilk dəfə dövrə salanda (məsələn, ilə) hesablanır |
| Query Provider | (LINQ to SQL, LINQ to Entities üçün) — metod zəncirini SQL-sorğulara və s. çevirir |
Vizual sxem
Kolleksiya (List<Product>, T[], ...)
│
▼
LINQ-metodlar (Where, OrderBy, Select...)
│
▼
Sorğu (IEnumerable<T>)
│
▼
Real icra (foreach, ToList, Count, ...)
6. Nümunə: tətbiqimizdə LINQ-zəncirinin addım-addım izahı
Yenidən Product sinfi ilə mini-tətbiqimizə qayıdırıq:
// Məhsul sinfi
class Product
{
public string Name { get; set; }
public double Price { get; set; }
}
Məhsulların siyahısı belədir:
var products = new List<Product>
{
new Product { Name = "Pendir", Price = 250.5 },
new Product { Name = "Çörək", Price = 30 },
new Product { Name = "Süd", Price = 80 },
new Product { Name = "Kofe", Price = 330 },
new Product { Name = "Yağ", Price = 140 }
};
Tutaq ki, tapşırıq belədir: 100 avrodan baha olan bütün məhsulların adlarını ekrana çıxar, qiymətə görə sırala.
Köhnə üsul
var filtered = new List<Product>();
foreach (var p in products)
{
if (p.Price > 100)
filtered.Add(p);
}
filtered.Sort((a, b) => a.Price.CompareTo(b.Price));
foreach (var p in filtered)
Console.WriteLine(p.Name);
LINQ üsulu
var expensive = products
.Where(p => p.Price > 100)
.OrderBy(p => p.Price)
.Select(p => p.Name);
foreach (var name in expensive)
Console.WriteLine(name);
Birinci sətrdə biz tapşırığın özünü təsvir edirik: "Qiyməti Price > 100 olanları filtrlə, qiymətə görə sırala, adlarını seç".
7. LINQ-un tez-tez istifadə olunan əməliyyatları və onların "köhnə üsul" analoqları
| Əməliyyat | "Köhnə üsul" məntiqi | LINQ |
|---|---|---|
| Filtrasiya | foreach + if + Add | |
| Proyeksiya (sahənin seçilməsi) | foreach + Add(field) | |
| Sıralama | Sort(comparer) | , |
| Unikal dəyərlər | foreach + contains + Add | |
| Sayma | foreach + counter++ | , |
| Şərtin yoxlanması | foreach + if | , |
| Birinci/sonuncunu tapmaq | foreach + if + break | , , |
| Say məhdudiyyəti | foreach + sayğac + break | , |
8. Praktika: tətbiqə LINQ əlavə edirik
Gəlin tətbiqimizin əsas kodunu (Product siyahısı) götürək və LINQ ilə bir neçə faydalı əməliyyat edək.
Filtrasiya və sıralama
// 200 avrodan ucuz məhsulları seç və ada görə sırala
var cheapProducts = products
.Where(p => p.Price < 200)
.OrderBy(p => p.Name);
foreach (var p in cheapProducts)
Console.WriteLine($"{p.Name}: {p.Price} avro");
Kolleksiyanın çevrilməsi (proyeksiya)
// Qiymətlərin siyahısını (double) al
var prices = products.Select(p => p.Price);
foreach (var price in prices)
Console.WriteLine(price);
İlk uyğun elementi tapmaq
// Adı "K" ilə başlayan ilk məhsul
var firstK = products.FirstOrDefault(p => p.Name.StartsWith("K"));
Console.WriteLine(firstK?.Name ?? "Tapılmadı");
100 avrodan baha məhsulların sayını tapmaq
int count = products.Count(p => p.Price > 100);
Console.WriteLine($"Belə məhsullar: {count} ədəd.");
Bu mühazirədən başlayaraq, kolleksiyaları emal etmək, filtrləmək, lazım olan məlumatları seçmək, aqreqasiyalar və daha çox şey üçün LINQ-dan aktiv istifadə edəcəyik. LINQ-un yeni metodlarını və imkanlarını (o cümlədən .NET 9-un yeniliklərini!) yaxın mühazirələrdə öyrənəcəyik, hələlik isə — sadə sorğularla eksperiment aparmaqdan çəkinmə, bu alətin gücünü hiss et!
GO TO FULL VERSION