Share via


Skriv relationer i LINQ-frågeåtgärder (C#)

Om du vill skriva frågor effektivt bör du förstå hur olika typer av variabler i en fullständig frågeåtgärd relaterar till varandra. Om du förstår dessa relationer kommer du lättare att förstå LINQ-exemplen och kodexemplen i dokumentationen. Dessutom kommer du att förstå vad som händer när variabler implicit skrivs med hjälp varav .

LINQ-frågeåtgärder skrivs starkt i datakällan, i själva frågan och i frågekörningen. Typen av variabler i frågan måste vara kompatibel med typen av element i datakällan och med typen av iterationsvariabel i -instruktionen foreach . Den här starka skrivningen garanterar att typfel fångas vid kompileringstillfället när de kan korrigeras innan användarna stöter på dem.

För att demonstrera dessa typrelationer använder de flesta av exemplen som följer explicit skrivning för alla variabler. Det sista exemplet visar hur samma principer tillämpas även när du använder implicit inmatning med hjälp varav .

Frågor som inte transformerar källdata

Följande bild visar en LINQ-till-objekt-frågeåtgärd som inte utför några transformeringar av data. Källan innehåller en sekvens med strängar och frågeutdata är också en sekvens med strängar.

Diagram som visar relationen mellan datatyper i en LINQ-fråga.

  1. Typargumentet för datakällan avgör typen av intervallvariabel.
  2. Typen av objekt som har valts avgör typen av frågevariabel. Här name är en sträng. Därför är frågevariabeln en IEnumerable<string>.
  3. Frågevariabeln itereras över i -instruktionen foreach . Eftersom frågevariabeln är en sekvens med strängar är iterationsvariabeln också en sträng.

Frågor som transformerar källdata

Följande bild visar en LINQ-till SQL-frågeåtgärd som utför en enkel transformering av data. Frågan tar en sekvens med Customer objekt som indata och väljer endast Name egenskapen i resultatet. Eftersom Name är en sträng genererar frågan en sekvens med strängar som utdata.

Diagram som visar en fråga som transformerar datatypen.

  1. Typargumentet för datakällan avgör typen av intervallvariabel.
  2. - select instruktionen Name returnerar egenskapen i stället för det fullständiga Customer objektet. Eftersom Name är en sträng är stringtypargumentet custNameQuery för , inte Customer.
  3. Eftersom custNameQuery är en sekvens med strängar måste loopens foreach iterationsvariabel också vara .string

Följande bild visar en något mer komplex transformering. -instruktionen select returnerar en anonym typ som bara samlar in två medlemmar i det ursprungliga Customer objektet.

Diagram som visar en mer komplex fråga som transformerar datatypen.

  1. Typargumentet för datakällan är alltid typen av intervallvariabel i frågan.
  2. Eftersom -instruktionen select genererar en anonym typ måste frågevariabeln implicit skrivas med hjälp varav .
  3. Eftersom frågevariabelns typ är implicit måste iterationsvariabeln i loopen foreach också vara implicit.

Låta kompilatorn härleda typinformation

Även om du bör förstå typrelationerna i en frågeåtgärd kan du välja att låta kompilatorn utföra allt arbete åt dig. Nyckelordsvar kan användas för valfri lokal variabel i en frågeåtgärd. Följande bild liknar exempel nummer 2 som beskrevs tidigare. Kompilatorn tillhandahåller dock den starka typen för varje variabel i frågeåtgärden.

Diagram som visar typflödet med implicit inmatning.

LINQ och generiska typer (C#)

LINQ-frågor baseras på generiska typer. Du behöver inte fördjupade kunskaper om generiska objekt innan du kan börja skriva frågor. Men du kanske vill förstå två grundläggande begrepp:

  1. När du skapar en instans av en allmän samlingsklass, till exempel List<T>, ersätter du "T" med den typ av objekt som listan ska innehålla. En lista med strängar uttrycks till exempel som List<string>och en lista med Customer objekt uttrycks som List<Customer>. En allmän lista är starkt skriven och ger många fördelar jämfört med samlingar som lagrar sina element som Object. Om du försöker lägga till en Customer i får List<string>du ett fel vid kompileringstillfället. Det är enkelt att använda allmänna samlingar eftersom du inte behöver utföra typgjutning vid körning.
  2. IEnumerable<T> är gränssnittet som gör att generiska samlingsklasser kan räknas upp med hjälp av -instruktionen foreach . Generiska samlingsklasser stöder IEnumerable<T> precis som icke-generiska samlingsklasser, till exempel ArrayList stöd IEnumerableför .

Mer information om generiska objekt finns i Generiska objekt.

IEnumerable<T-variabler> i LINQ-frågor

LINQ-frågevariabler skrivs som IEnumerable<T> eller en härledd typ, till exempel IQueryable<T>. När du ser en frågevariabel som skrivs som IEnumerable<Customer>betyder det bara att frågan, när den körs, skapar en sekvens med noll eller fler Customer objekt.

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

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

Låta kompilatorn hantera allmänna typdeklarationer

Om du vill kan du undvika allmän syntax med hjälp av nyckelordet var . Nyckelordet var instruerar kompilatorn att härleda typen av en frågevariabel genom att titta på datakällan som anges i from -satsen. I följande exempel skapas samma kompilerade kod som i föregående exempel:

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

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

Nyckelordet var är användbart när variabeltypen är uppenbar eller när det inte är så viktigt att uttryckligen ange kapslade generiska typer, till exempel de som skapas av gruppfrågor. I allmänhet rekommenderar vi att du, om du använder var, inser att det kan göra koden svårare för andra att läsa. Mer information finns i Implicit inskrivna lokala variabler.