Funkcje C# obsługujące LINQ

Wyrażenia kwerend

Wyrażenia zapytań używają składni deklaratywnej podobnej do języka SQL lub XQuery do wykonywania zapytań dotyczących System.Collections.Generic.IEnumerable<T> kolekcji. W czasie kompilacji składnia zapytania jest konwertowana na wywołania metody do implementacji standardowych metod zapytań dostawcy LINQ. Aplikacje kontrolują standardowe operatory zapytań, które znajdują się w zakresie, określając odpowiednią przestrzeń nazw za using pomocą dyrektywy. Poniższe wyrażenie zapytania przyjmuje tablicę ciągów, grupuje je zgodnie z pierwszym znakiem w ciągu i porządkuje grupy.

var query = from str in stringArray
            group str by str[0] into stringGroup
            orderby stringGroup.Key
            select stringGroup;

Niejawnie wpisane zmienne (var)

Możesz użyć modyfikatora var , aby poinstruować kompilator wywnioskować i przypisać typ, jak pokazano poniżej:

var number = 5;
var name = "Virginia";
var query = from str in stringArray
            where str[0] == 'm'
            select str;

Zmienne zadeklarowane jako var są silnie typizowane, podobnie jak zmienne, których typ został określony jawnie. Użycie var umożliwia tworzenie typów anonimowych, ale tylko dla zmiennych lokalnych. Aby uzyskać więcej informacji, zobacz Niejawnie wpisane zmienne lokalne.

Inicjatory obiektów i kolekcji

Inicjatory obiektów i kolekcji umożliwiają inicjowanie obiektów bez jawnego wywoływania konstruktora dla obiektu. Inicjatory są zwykle używane w wyrażeniach zapytań podczas projekcji danych źródłowych do nowego typu danych. Przy założeniu, że klasa o nazwie Customer z publicznymi Name i Phone właściwościami, inicjator obiektu może służyć jako w następującym kodzie:

var cust = new Customer { Name = "Mike", Phone = "555-1212" };

Kontynuując swoją Customer klasę, załóżmy, że istnieje źródło danych o nazwie IncomingOrdersi że dla każdego zamówienia z dużą wartością OrderSizechcesz utworzyć nową Customer na podstawie tej kolejności. Zapytanie LINQ można wykonać w tym źródle danych i użyć inicjowania obiektu w celu wypełnienia kolekcji:

var newLargeOrderCustomers = from o in IncomingOrders
                            where o.OrderSize > 5
                            select new Customer { Name = o.Name, Phone = o.Phone };

Źródło danych może mieć więcej właściwości zdefiniowanych niż Customer klasa, na OrderSizeprzykład , ale z inicjowaniem obiektu dane zwracane z zapytania są formowane w żądany typ danych; wybierasz dane, które są istotne dla klasy. W rezultacie masz System.Collections.Generic.IEnumerable<T> teraz wypełniony nowy Customerelement, którego potrzebujesz. Powyższy przykład można również napisać w składni metody LINQ:

var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });

Począwszy od języka C# 12, można użyć wyrażenia kolekcji do zainicjowania kolekcji.

Aby uzyskać więcej informacji, zobacz:

Typy anonimowe

Kompilator tworzy typ anonimowy. Nazwa typu jest dostępna tylko dla kompilatora. Typy anonimowe zapewniają wygodny sposób grupowania zestawu właściwości tymczasowo w wyniku zapytania bez konieczności definiowania oddzielnego nazwanego typu. Typy anonimowe są inicjowane przy użyciu nowego wyrażenia i inicjatora obiektów, jak pokazano poniżej:

select new {name = cust.Name, phone = cust.Phone};

Począwszy od języka C# 7, możesz użyć krotki do tworzenia nienazwanych typów.

Metody rozszerzania

Metoda rozszerzenia to metoda statyczna, którą można skojarzyć z typem, aby można było ją wywołać tak, jakby była to metoda wystąpienia w typie. Ta funkcja umożliwia, w efekcie, "dodawanie" nowych metod do istniejących typów bez ich faktycznego modyfikowania. Standardowe operatory zapytań to zestaw metod rozszerzeń, które zapewniają funkcje zapytań LINQ dla dowolnego typu, który implementuje metodę IEnumerable<T>.

Wyrażenia lambda

Wyrażenia lambda to funkcja śródliniowa, która używa => operatora do oddzielania parametrów wejściowych od treści funkcji i może zostać przekonwertowana w czasie kompilacji na delegata lub drzewo wyrażeń. W programowaniu LINQ występują wyrażenia lambda podczas wykonywania wywołań metod bezpośrednich do standardowych operatorów zapytań.

Wyrażenia jako dane

Obiekty zapytania są komponowalne, co oznacza, że można zwrócić zapytanie z metody. Obiekty reprezentujące zapytania nie przechowują wynikowej kolekcji, ale raczej kroki umożliwiające wygenerowanie wyników w razie potrzeby. Zaletą zwracania obiektów zapytań z metod jest to, że można je dodatkowo skomponować lub zmodyfikować. W związku z tym każda zwracana wartość lub out parametr metody zwracającej zapytanie musi również mieć ten typ. Jeśli metoda zmaterializuje zapytanie do konkretnego List<T> lub Array typu, zwraca wyniki zapytania zamiast samego zapytania. Zmienna kwerendy zwracana z metody nadal może być komponowana lub modyfikowana.

W poniższym przykładzie pierwsza metoda QueryMethod1 zwraca zapytanie jako wartość zwracaną, a druga metoda QueryMethod2 zwraca zapytanie jako out parametr (returnQ w przykładzie). W obu przypadkach jest to zapytanie, które jest zwracane, a nie wyniki zapytania.

IEnumerable<string> QueryMethod1(int[] ints) =>
    from i in ints
    where i > 4
    select i.ToString();

void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
    returnQ =
        from i in ints
        where i < 4
        select i.ToString();

int[] nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

var myQuery1 = QueryMethod1(nums);

Zapytanie myQuery1 jest wykonywane w następującej pętli foreach.

foreach (var s in myQuery1)
{
    Console.WriteLine(s);
}

Umieść wskaźnik myszy, myQuery1 aby zobaczyć jego typ.

Możesz również wykonać zapytanie zwrócone bezpośrednio bez QueryMethod1 użycia polecenia myQuery1.

foreach (var s in QueryMethod1(nums))
{
    Console.WriteLine(s);
}

Umieść wskaźnik myszy nad wywołaniem, aby zobaczyć QueryMethod1 jego typ zwracany.

QueryMethod2 Zwraca zapytanie jako wartość jego out parametru:

QueryMethod2(nums, out IEnumerable<string> myQuery2);

// Execute the returned query.
foreach (var s in myQuery2)
{
    Console.WriteLine(s);
}

Zapytanie można modyfikować przy użyciu kompozycji zapytań. W tym przypadku poprzedni obiekt zapytania jest używany do tworzenia nowego obiektu zapytania. Ten nowy obiekt zwraca inne wyniki niż oryginalny obiekt zapytania.

myQuery1 =
    from item in myQuery1
    orderby item descending
    select item;

// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
    Console.WriteLine(s);
}