Nesneler koleksiyonunu sorgulama

"LINQ to Objects" terimi, LINQ to SQLveya LINQ to XML gibi bir ara LINQ sağlayıcısı veya API'nin kullanılmadan doğrudan herhangi IEnumerable bir veya IEnumerable<T> koleksiyon ile LINQ sorgularının kullanımını ifade eder. LINQ kullanarak , Arrayveya Dictionary<TKey,TValue>gibi List<T>numaralandırılabilir koleksiyonları sorgulayabilirsiniz. Koleksiyon kullanıcı tanımlı olabilir veya bir .NET API tarafından döndürülebilir. LINQ yaklaşımında, ne almak istediğinizi açıklayan bildirim temelli kod yazarsınız.

Buna ek olarak, LINQ sorguları geleneksel foreach döngülere göre üç temel avantaj sunar:

  • Özellikle birden çok koşul filtrelenirken daha kısa ve okunabilirdirler.
  • En az uygulama koduyla güçlü filtreleme, sıralama ve gruplandırma özellikleri sağlar.
  • Bunlar çok az değişiklikle veya hiç değişiklik yapılmadan diğer veri kaynaklarına taşınabilir.

Genel olarak, veriler üzerinde gerçekleştirmek istediğiniz işlem ne kadar karmaşık olursa, geleneksel yineleme teknikleri yerine LINQ kullanarak o kadar avantajlı olursunuz.

Bu örnekte, bir nesne listesi üzerinde basit bir sorgunun nasıl gerçekleştir yapılacağı gösterilmektedir Student . Her Student nesne, öğrenci hakkında bazı temel bilgiler ve dört sınavdaki öğrencinin puanlarını temsil eden bir liste içerir.

Not

Bu bölümdeki diğer birçok örnek aynı Student sınıfı ve students koleksiyonu kullanır.

class Student
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int ID { get; set; }
    public GradeLevel? Year { get; set; }
    public List<int> ExamScores { get; set; }

    public Student(string FirstName, string LastName, int ID, GradeLevel Year, List<int> ExamScores)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
        this.ID = ID;
        this.Year = Year;
        this.ExamScores = ExamScores;
    }

    public Student(string FirstName, string LastName, int StudentID, List<int>? ExamScores = null)
    {
        this.FirstName = FirstName;
        this.LastName = LastName;
        ID = StudentID;
        this.ExamScores = ExamScores ?? [];
    }

    public static List<Student> students =
    [
        new(
            FirstName: "Terry", LastName: "Adams", ID: 120,
            Year: GradeLevel.SecondYear,
            ExamScores: [99, 82, 81, 79]
        ),
        new(
            "Fadi", "Fakhouri", 116,
            GradeLevel.ThirdYear,
            [99, 86, 90, 94]
        ),
        new(
            "Hanying", "Feng", 117,
            GradeLevel.FirstYear,
            [93, 92, 80, 87]
        ),
        new(
            "Cesar", "Garcia", 114,
            GradeLevel.FourthYear,
            [97, 89, 85, 82]
        ),
        new(
            "Debra", "Garcia", 115,
            GradeLevel.ThirdYear,
            [35, 72, 91, 70]
        ),
        new(
            "Hugo", "Garcia", 118,
            GradeLevel.SecondYear,
            [92, 90, 83, 78]
        ),
        new(
            "Sven", "Mortensen", 113,
            GradeLevel.FirstYear,
            [88, 94, 65, 91]
        ),
        new(
            "Claire", "O'Donnell", 112,
            GradeLevel.FourthYear,
            [75, 84, 91, 39]
        ),
        new(
            "Svetlana", "Omelchenko", 111,
            GradeLevel.SecondYear,
            [97, 92, 81, 60]
        ),
        new(
            "Lance", "Tucker", 119,
            GradeLevel.ThirdYear,
            [68, 79, 88, 92]
        ),
        new(
            "Michael", "Tucker", 122,
            GradeLevel.FirstYear,
            [94, 92, 91, 91]
        ),
        new(
            "Eugene", "Zabokritski", 121,
            GradeLevel.FourthYear,
            [96, 85, 91, 60]
        )
    ];
}

enum GradeLevel
{
    FirstYear = 1,
    SecondYear,
    ThirdYear,
    FourthYear
};

Örnek

Aşağıdaki sorgu, ilk sınavında 90 veya daha yüksek puan alan öğrencileri döndürür.

void QueryHighScores(int exam, int score)
{
    var highScores =
        from student in students
        where student.ExamScores[exam] > score
        select new
        {
            Name = student.FirstName,
            Score = student.ExamScores[exam]
        };

    foreach (var item in highScores)
    {
        Console.WriteLine($"{item.Name,-15}{item.Score}");
    }
}

QueryHighScores(0, 90);

Bu sorgu, deneme yapmanızı sağlamak için kasıtlı olarak basittir. Örneğin, yan tümcesinde where daha fazla koşul deneyebilir veya sonuçları sıralamak için bir orderby yan tümce kullanabilirsiniz.

Standart sorgu işleçlerinin yürütme şekline göre sınıflandırılması

Standart sorgu işleci yöntemlerinin LINQ to Objects uygulamaları iki ana yoldan biriyle yürütülür: anında veya ertelenmiş. Ertelenmiş yürütme kullanan sorgu işleçleri ayrıca iki kategoriye ayrılabilir: akış ve akış dışı. Farklı sorgu işleçlerinin nasıl yürütüldüğünü biliyorsanız, belirli bir sorgudan elde ettiğiniz sonuçları anlamanıza yardımcı olabilir. Bu durum özellikle veri kaynağı değişiyorsa veya başka bir sorgunun üzerine sorgu oluşturuyorsanız geçerlidir. Bu konu başlığında standart sorgu işleçleri yürütme şekline göre sınıflandırır.

Anlık

Anında yürütme, veri kaynağının okunduğu ve işlemin bir kez gerçekleştirildiği anlamına gelir. Skaler sonuç döndüren tüm standart sorgu işleçleri hemen yürütülür. veya Enumerable.ToArray yöntemlerini kullanarak bir sorguyu Enumerable.ToList hemen yürütülmeye zorlayabilirsiniz. Anında yürütme, sorgu bildirimini değil sorgu sonuçlarının yeniden kullanılmasını sağlar. Sonuçlar bir kez alınır ve daha sonra kullanılmak üzere depolanır.

Ertelenmiş

Ertelenmiş yürütme, işlemin sorgunun bildirildiği kod noktasında gerçekleştirilmediği anlamına gelir. İşlem yalnızca sorgu değişkeni numaralandırıldığında, örneğin bir foreach deyimi kullanılarak gerçekleştirilir. Bu, sorguyu yürütmenin sonuçlarının, sorgu tanımlandığında değil, sorgu yürütülürken veri kaynağının içeriğine bağlı olduğu anlamına gelir. Sorgu değişkeni birden çok kez numaralandırılırsa, sonuçlar her seferinde farklı olabilir. Dönüş türü IEnumerable<T> ertelenmiş bir şekilde olan veya IOrderedEnumerable<TElement> yürütülen neredeyse tüm standart sorgu işleçleri. Ertelenmiş yürütme, sorgu sonuçları her yinelendiğinde sorgu güncelleştirilmiş verileri veri kaynağından aldığından sorgunun yeniden kullanılmasını sağlar.

Ertelenmiş yürütme kullanan sorgu işleçleri ayrıca akış veya akış dışı olarak sınıflandırılabilir.

Akışlar

Akış işleçlerinin öğeleri vermeden önce tüm kaynak verileri okuması gerekmez. Yürütme sırasında, bir akış işleci her kaynak öğe üzerinde okundukça işlemini gerçekleştirir ve uygunsa öğesini verir. Akış işleci, sonuç öğesi üretilene kadar kaynak öğeleri okumaya devam eder. Bu, bir sonuç öğesi üretmek için birden fazla kaynak öğenin okunabileceği anlamına gelir.

Akış dışı

Akış dışı işleçlerin bir sonuç öğesi elde etmeden önce tüm kaynak verileri okuması gerekir. Sıralama veya gruplandırma gibi işlemler bu kategoriye girer. Yürütme sırasında akış dışı sorgu işleçleri tüm kaynak verileri okur, bir veri yapısına ekler, işlemi gerçekleştirir ve sonuçta elde edilen öğeleri verir.

Sınıflandırma tablosu

Aşağıdaki tablo, her standart sorgu işleci yöntemini yürütme yöntemine göre sınıflandırır.

Not

bir işleç iki sütunda işaretlenmişse, işleme iki giriş dizisi dahil edilir ve her dizi farklı değerlendirilir. Bu gibi durumlarda, her zaman parametre listesindeki ertelenmiş, akış biçiminde değerlendirilen ilk sıradır.

Standart sorgu işleci Dönüş türü Anında yürütme Ertelenen akış yürütme Ertelenmiş Akışsız yürütme
Aggregate TSource X
All Boolean X
Any Boolean X
AsEnumerable IEnumerable<T> X
Average Tek sayısal değer X
Cast IEnumerable<T> X
Concat IEnumerable<T> X
Contains Boolean X
Count Int32 X
DefaultIfEmpty IEnumerable<T> X
Distinct IEnumerable<T> X
ElementAt TSource X
ElementAtOrDefault TSource? X
Empty IEnumerable<T> X
Except IEnumerable<T> X X
First TSource X
FirstOrDefault TSource? X
GroupBy IEnumerable<T> X
GroupJoin IEnumerable<T> X X
Intersect IEnumerable<T> X X
Join IEnumerable<T> X X
Last TSource X
LastOrDefault TSource? X
LongCount Int64 X
Max Tek sayısal değer, TSourceveya TResult? X
Min Tek sayısal değer, TSourceveya TResult? X
OfType IEnumerable<T> X
OrderBy IOrderedEnumerable<TElement> X
OrderByDescending IOrderedEnumerable<TElement> X
Range IEnumerable<T> X
Repeat IEnumerable<T> X
Reverse IEnumerable<T> X
Select IEnumerable<T> X
SelectMany IEnumerable<T> X
SequenceEqual Boolean X
Single TSource X
SingleOrDefault TSource? X
Skip IEnumerable<T> X
SkipWhile IEnumerable<T> X
Sum Tek sayısal değer X
Take IEnumerable<T> X
TakeWhile IEnumerable<T> X
ThenBy IOrderedEnumerable<TElement> X
ThenByDescending IOrderedEnumerable<TElement> X
ToArray TSource[] Dizi X
ToDictionary Dictionary<TKey,TValue> X
ToList IList<T> X
ToLookup ILookup<TKey,TElement> X
Union IEnumerable<T> X
Where IEnumerable<T> X

Ayrıca bkz.