CodeGym /Kurslar /C# SELF /Məlumatların proyeksiyası ...

Məlumatların proyeksiyası Select ilə

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Seriala baxanda, həmişə bütün personajlar haqqında tam məlumat almırsan, yalnız süjet üçün lazım olanı bilirsən. Proqramlaşdırmada da tez-tez belə hallar olur: bizə obyektin hamısı yox, yalnız bəzi sahələri, dəyərləri və ya hətta onların əsasında hansısa hesablamalar lazımdır.

Proyeksiya LINQ-də — bu, ilkin ardıcıllığın elementlərini yeni formaya çevirməkdir. Adətən Select metodu ilə. Select haqqında belə düşün: bu elə bir sehrli maşındır ki, hər elementi götürür, ona funksiya tətbiq edir və nəticəni qaytarır. Vəssalam, heç bir fokus yoxdur.

Proyeksiya nə vaxt lazımdır?

  • Yalnız istifadəçilərin adlarını çıxarmaq istəyirik, bütün məlumatları yox.
  • Email göndərişi hazırlayırıq: müştəri obyektindən yalnız ünvan və ad götürürük.
  • Hesablama edirik: məhsulun qiymətinə vergi əlavə edib yeni kolleksiya alırıq.
  • UI üçün: yalnız bir hissə məlumat göstərmək lazımdır, interfeysi yükləməmək üçün.

2. Select metodu: sintaksis və əsas iş prinsipi

Əsas sintaksis

LINQ iki stil dəstəkləyir: metodik (Method Syntax) və sorğu (Query Syntax). Select üçün hər iki stildə nəticə eynidir.

Metod-sintaksis

var query = myCollection.Select(x => x.NeyiQaytarmaq);

Burada x — kolleksiyadakı hər element üçün dəyişəndir, sağda isə — elementi lazım olan şeyə çevirən ifadədir.

Sorğu-sintaksis

var query = from x in myCollection
            select x.NeyiQaytarmaq;

Burada hər şey bir az SQL-ə bənzəyir.

Sadə nümunə: ədədlər siyahısı

var numbers = new List<int> { 1, 2, 3, 4, 5 };
// Kvadratlarını almaq istəyirəm
var squares = numbers.Select(n => n * n);

foreach (var s in squares)
{
    Console.WriteLine(s); // 1, 4, 9, 16, 25
}

İndi biz ədədlər kolleksiyasını onların kvadratları kolleksiyasına çevirdik — bir anda, əl ilə dövrə ehtiyac olmadan!

Nümunə 2

Əvvəlki nümunələrdə bizdə artıq Product sinfi var idi:

public class Product
{
    public string Name { get; set; }
    public double Price { get; set; }
}

Güman edək ki, bizdə siyahı var:

var products = new List<Product>
{
    new Product { Name = "Şokolad", Price = 120 },
    new Product { Name = "Pendir", Price = 250 },
    new Product { Name = "Çörək", Price = 55 }
};

Əgər biz sadəcə bütün məhsulların adlarını almaq istəyiriksə, bütün obyekt lazım deyil, düzdür? Bizə yalnız adlar siyahısı lazımdır:

var names = products.Select(p => p.Name);
foreach (var name in names)
{
    Console.WriteLine(name); // Şokolad, Pendir, Çörək
}

3. Qaytarılan kolleksiya — hansı variantlar var?

Diqqət et ki, Select həmişə kolleksiya qaytarır (dəqiq desək — IEnumerable<TOutput>), burada TOutput — funksiyanın nəticəsinin tipidir. Sən özün müəyyən edirsən, bu nə olacaq: string, ədəd, anonim tip, hətta yeni obyekt.

Yeni tipə proyeksiya

Məsələn, xam obyekt yox, onun "proyeksiyası" lazımdır:

var projections = products.Select(p => new { p.Name, QiymetVergiIle = p.Price * 1.2 });

foreach (var item in projections)
{
    Console.WriteLine($"{item.Name}: {item.QiymetVergiIle}");
}

Burada biz yeni anonim obyektlər kolleksiyası yaratdıq — ad və təsəvvür olunan ƏDV ilə qiymət!

4. Yeni sinif və ya anonim tip qaytarırıq

Sən seçə bilərsən: nəticə üçün tam siniflər yaratmaq və ya struktur yalnız "burada və indi" lazımdırsa, anonim tiplərlə kifayətlənmək.

Anonim tiplər

var result = products.Select(p => new { Ad = p.Name, KöhnəQiymət = p.Price, YeniQiymət = p.Price + 40 });
foreach (var p in result)
{
    Console.WriteLine($"{p.Ad}: Əvvəl {p.KöhnəQiymət}, indi {p.YeniQiymət}");
}

Anonim tiplər nəticəni tez formalaşdırmaq üçün rahatdır, xüsusən bir əməliyyat üçün ayrıca sinif yaratmağa ehtiyac yoxdursa.

Proyeksiya üçün öz sinifimizi istifadə edirik

Yeni sinif yaradaq:

public class ProductDto
{
    public string Name { get; set; }
    public double PriceWithTax { get; set; }
}

İndi LINQ-sorğusunda:

var productsWithTax = products.Select(p => new ProductDto
{
    Name = p.Name,
    PriceWithTax = p.Price * 1.2
});

foreach (var p in productsWithTax)
{
    Console.WriteLine($"{p.Name}: {p.PriceWithTax}");
}

5. Daxili kolleksiyalara və xüsusiyyətlərə çıxış

Bəs obyektin içində kolleksiya varsa? Məsələn, hər istifadəçinin sifarişlər siyahısı var.

public class User
{
    public string Name { get; set; }
    public List<Product> Purchases { get; set; }
}

Bütün alış-veriş siyahılarını almaq istəyirsən? Problem deyil!

var allPurchases = users.Select(u => u.Purchases);

foreach (var purchaseList in allPurchases)
{
    foreach (var product in purchaseList)
    {
        Console.WriteLine(product.Name);
    }
}

Vacibdir! Bu halda bizdə "düz" məhsullar siyahısı yox, kolleksiyalar kolleksiyası alındı. Bəs bütün istifadəçilərin məhsullarını BİR siyahıda necə toplamaq olar? Bu, növbəti dərsin mövzusu olacaq — orada SelectMany ilə tanış olacağıq.

6. Faydalı nüanslar

Kolleksiya tipinə çevirmək: ToList() və dostları

Select IEnumerable<T> qaytarır. Əgər adi siyahı (List<T>) istəyirsənsə, sadəcə .ToList() əlavə et:

var nameList = products.Select(p => p.Name).ToList();

İndi sənin tam siyahın var, istədiyin kimi işlədə bilərsən.

Elementin indeksindən istifadə

Bəzən faydalıdır bilmək ki, kolleksiyada hansı element işlənir. Select metodunun overload-u var:

var indexed = products.Select((product, index) => new { Index = index, Name = product.Name });
foreach (var item in indexed)
{
    Console.WriteLine($"{item.Index}: {item.Name}");
}

Beləliklə, məsələn, nömrələnmiş siyahılar üçün məlumat hazırlamaq olar.

Proyeksiya proqramlaşdırmada

Select bacarığı — tez-tez müsahibələrdə verilən sualdır. Bu konstruktsiyasız müasir tətbiqləri təsəvvür etmək çətindir:

  • Yalnız lazım olan məlumatların DB və ya xarici servislərdən seçilməsi.
  • Tətbiq qatları arasında məlumat ötürülməsi üçün hazırlıq.
  • Ekranda göstərmək və ya şəbəkə ilə göndərmək üçün uyğun formata çevirmək.
  • Yaddaşa qənaət (bütün obyekt yox, yalnız lazım olan sahələr).

Böyük həcmli məlumatlarla işləyən şirkətlər çox vaxt əsas biznes-logikanı bunun üzərində qurur.

7. Tipik səhvlər və xüsusiyyətlər

Bəzən yeni başlayan proqramçılar əsəbi bug-larla qarşılaşır — adətən təxirə salınmış icra (deferred execution) LINQ-də necə işlədiyini tam anlamadıqları üçün. Məsələn, Select çağırandan sonra sorğu dərhal icra olunmur — yalnız kolleksiyanı həqiqətən iterasiya edəndə (foreach, ToList() və s.). Bu, "emal borusu" qurmağa imkan verir, amma bəzən nəticə dəyişir, əgər ilkin məlumatlar sorğunun nəticəsindən istifadə etməzdən əvvəl dəyişibsə.

Həmçinin unutma ki, Select ilkin kolleksiyanı dəyişmir — o, yenisini qurur. Ona görə də, əgər products-da yeni sahələr tapacağını gözləyirsənsə products.Select(...) sonra, bu baş verməyəcək.

null işləmə: əgər proyeksiya potensial null sahələrə müraciət edirsə, bunu nəzərə almağı unutma. C# 8+ versiyasında, əgər NullReferenceException almaq mümkündürsə, kompilyator xəbərdarlıq verir.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION