Udostępnij za pośrednictwem


Relacje typu w operacjach kwerend LINQ (C#)

Aby efektywnie pisać zapytania, należy zrozumieć, jak typy zmiennych w pełnej operacji zapytania odnoszą się do siebie nawzajem. Jeśli rozumiesz te relacje, łatwiej zrozumiesz przykłady LINQ i przykłady kodu w dokumentacji. Ponadto dowiesz się, co się dzieje, gdy zmienne są niejawnie wpisywane przy użyciu metody var.

Operacje zapytań LINQ są silnie typizowane w źródle danych, w samym zapytaniu i w wykonaniu zapytania. Typ zmiennych w zapytaniu musi być zgodny z typem elementów w źródle danych i typem zmiennej iteracji w instrukcji foreach . To silne wpisywanie gwarantuje, że błędy typu są przechwytywane w czasie kompilacji, gdy można je poprawić przed ich napotkaniem przez użytkowników.

Aby zademonstrować relacje typów, większość przykładów, które są zgodne z jawnym wpisywaniem dla wszystkich zmiennych. W ostatnim przykładzie pokazano, jak te same zasady mają zastosowanie nawet w przypadku używania niejawnego pisania przy użyciu polecenia var.

Zapytania, które nie przekształcają danych źródłowych

Na poniższej ilustracji przedstawiono operację zapytania LINQ to Objects, która nie wykonuje żadnych przekształceń na danych. Źródło zawiera sekwencję ciągów, a dane wyjściowe zapytania są również sekwencją ciągów.

Diagram przedstawiający relację typów danych w zapytaniu LINQ.

  1. Argument typu źródła danych określa typ zmiennej zakresu.
  2. Typ wybranego obiektu określa typ zmiennej kwerendy. Oto name ciąg. W związku z tym zmienna kwerendy to IEnumerable<string>.
  3. Zmienna kwerendy jest iteracja w instrukcji foreach . Ponieważ zmienna kwerendy jest sekwencją ciągów, zmienna iteracji jest również ciągiem.

Zapytania przekształcające dane źródłowe

Na poniższej ilustracji przedstawiono operację zapytania LINQ to SQL, która wykonuje prostą transformację danych. Zapytanie przyjmuje sekwencję Customer obiektów jako dane wejściowe i wybiera tylko Name właściwość w wyniku. Ponieważ Name jest ciągiem, zapytanie tworzy sekwencję ciągów jako dane wyjściowe.

Diagram przedstawiający zapytanie, które przekształca typ danych.

  1. Argument typu źródła danych określa typ zmiennej zakresu.
  2. Instrukcja select zwraca Name właściwość zamiast kompletnego Customer obiektu. Ponieważ Name jest ciągiem, argument typu to custNameQuerystring, a nie Customer.
  3. Ponieważ custNameQuery jest sekwencją ciągów, foreach zmienna iteracji pętli musi być również zmienną string.

Na poniższej ilustracji przedstawiono nieco bardziej złożoną transformację. Instrukcja select zwraca typ anonimowy, który przechwytuje tylko dwa elementy członkowskie oryginalnego Customer obiektu.

Diagram przedstawiający bardziej złożone zapytanie, które przekształca typ danych.

  1. Argument typu źródła danych jest zawsze typem zmiennej zakresu w zapytaniu.
  2. select Ponieważ instrukcja generuje typ anonimowy, zmienna kwerendy musi być niejawnie wpisywana przy użyciu metody var.
  3. Ponieważ typ zmiennej kwerendy jest niejawny, zmienna iteracji w foreach pętli musi być również niejawna.

Zezwalanie kompilatorowi na informacje o typie wnioskowania

Chociaż należy zrozumieć relacje typów w operacji zapytania, możesz zezwolić kompilatorowi na wykonywanie wszystkich zadań. Zmienna var słowa kluczowego może być używana dla dowolnej zmiennej lokalnej w operacji zapytania. Poniższa ilustracja jest podobna do przykładowej liczby 2, która została omówiona wcześniej. Jednak kompilator dostarcza silny typ dla każdej zmiennej w operacji zapytania.

Diagram przedstawiający przepływ typu z niejawnymi wpisywaniem.

LINQ i typy ogólne (C#)

Zapytania LINQ są oparte na typach ogólnych. Nie potrzebujesz dogłębnej wiedzy na temat typów ogólnych przed rozpoczęciem pisania zapytań. Warto jednak zapoznać się z dwoma podstawowymi pojęciami:

  1. Podczas tworzenia wystąpienia klasy kolekcji ogólnej, takiej jak List<T>, zastąp ciąg "T" typem obiektów, które będą przechowywane na liście. Na przykład lista ciągów jest wyrażona jako List<string>, a lista Customer obiektów jest wyrażona jako List<Customer>. Lista ogólna jest silnie typizowana i zapewnia wiele korzyści w przypadku kolekcji, które przechowują swoje elementy jako Object. Jeśli spróbujesz dodać element Customer do List<string>elementu , podczas kompilacji wystąpi błąd. Łatwo jest używać kolekcji ogólnych, ponieważ nie trzeba wykonywać rzutowania typu w czasie wykonywania.
  2. IEnumerable<T> to interfejs, który umożliwia wyliczanie klas kolekcji ogólnych przy użyciu instrukcji foreach . Klasy kolekcji ogólnych obsługują IEnumerable<T> tak samo, jak klasy kolekcji nieogólne, takie jak ArrayList obsługa IEnumerable.

Aby uzyskać więcej informacji na temat typów ogólnych, zobacz Ogólne.

Zmienne IEnumerable<T> w zapytaniach LINQ

Zmienne zapytania LINQ są wpisywane jako IEnumerable<T> lub typ pochodny, taki jak IQueryable<T>. Gdy zobaczysz zmienną kwerendy, która jest typowana jako IEnumerable<Customer>, oznacza to tylko, że zapytanie, gdy jest wykonywane, spowoduje utworzenie sekwencji zero lub więcej Customer obiektów.

IEnumerable<Customer> customerQuery =
    from cust in customers
    where cust.City == "London"
    select cust;

foreach (Customer customer in customerQuery)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

Umożliwienie kompilatorowi obsługi deklaracji typów ogólnych

Jeśli wolisz, możesz uniknąć składni ogólnej przy użyciu słowa kluczowego var . Słowo var kluczowe nakazuje kompilatorowi wnioskowanie typu zmiennej zapytania przez przyjrzenie się źródle danych określonemu w klauzuli from . Poniższy przykład tworzy ten sam skompilowany kod co w poprzednim przykładzie:

var customerQuery2 =
    from cust in customers
    where cust.City == "London"
    select cust;

foreach(var customer in customerQuery2)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

Słowo var kluczowe jest przydatne, gdy typ zmiennej jest oczywisty lub gdy nie jest tak ważne, aby jawnie określić zagnieżdżone typy ogólne, takie jak te, które są generowane przez zapytania grupy. Ogólnie rzecz biorąc, zalecamy, aby jeśli używasz varmetody , należy pamiętać, że może to utrudnić innym osobom odczytywanie kodu. Aby uzyskać więcej informacji, zobacz Niejawnie wpisane zmienne lokalne.