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 var
av .
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 var
av .
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.
- Typargumentet för datakällan avgör typen av intervallvariabel.
- 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 enIEnumerable<string>
. - 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.
- Typargumentet för datakällan avgör typen av intervallvariabel.
- -
select
instruktionenName
returnerar egenskapen i stället för det fullständigaCustomer
objektet. EftersomName
är en sträng ärstring
typargumentetcustNameQuery
för , inteCustomer
. - Eftersom
custNameQuery
är en sekvens med strängar måste loopensforeach
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.
- Typargumentet för datakällan är alltid typen av intervallvariabel i frågan.
- Eftersom -instruktionen
select
genererar en anonym typ måste frågevariabeln implicit skrivas med hjälpvar
av . - 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.
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:
- 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 medCustomer
objekt uttrycks somList<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 enCustomer
i fårList<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. - 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.