Típuskapcsolatok a LINQ-lekérdezési műveletekben (C#)

A lekérdezések hatékony írásához tisztában kell lennie azzal, hogy egy teljes lekérdezési művelet változóinak típusai hogyan kapcsolódnak egymáshoz. Ha tisztában van ezekkel a kapcsolatokkal, könnyebben megértheti a LINQ-mintákat és a kódmintákat a dokumentációban. Emellett meg fogja érteni, hogy mi történik, ha a változók implicit módon vannak begépelve a használatával var.

A LINQ lekérdezési műveletek erősen be vannak állítva az adatforrásba, magában a lekérdezésbe és a lekérdezés végrehajtásába. A lekérdezés változóinak típusának kompatibilisnek kell lennie az adatforrás elemeinek típusával és az utasítás iterációs foreach változójának típusával. Ez az erős gépelés garantálja, hogy a típushibák a fordításkor jelennek meg, amikor azok kijavíthatók, mielőtt a felhasználók találkoznának velük.

Ezeknek a típuskapcsolatoknak a bemutatásához az alábbi példák többsége explicit gépelést használ az összes változóhoz. Az utolsó példa bemutatja, hogyan érvényesek ugyanazok az alapelvek akkor is, ha implicit gépelést használ a használatával var.

Olyan lekérdezések, amelyek nem alakítják át a forrásadatokat

Az alábbi ábrán egy LINQ to Objects lekérdezési művelet látható, amely nem végez átalakításokat az adatokon. A forrás sztringsorozatot tartalmaz, a lekérdezés kimenete pedig sztringek sorozata is.

Diagram that shows the relation of data types in a LINQ query.

  1. Az adatforrás típusargumentuma határozza meg a tartományváltozó típusát.
  2. A kiválasztott objektum típusa határozza meg a lekérdezési változó típusát. Itt name van egy sztring. Ezért a lekérdezési változó egy IEnumerable<string>.
  3. A lekérdezési változó iterated over in the foreach utasítás. Mivel a lekérdezési változó sztringek sorozata, az iterációs változó szintén sztring.

Lekérdezések, amelyek átalakítják a forrásadatokat

Az alábbi ábrán egy LINQ–SQL-lekérdezési művelet látható, amely egyszerű átalakítást hajt végre az adatokon. A lekérdezés bemenetként egy objektumsorozatot Customer vesz fel, és csak az Name eredmény tulajdonságát választja ki. Mivel Name egy sztringről van szó, a lekérdezés kimenetként sztringsorozatot hoz létre.

Diagram showing a query that transforms the data type.

  1. Az adatforrás típusargumentuma határozza meg a tartományváltozó típusát.
  2. Az select utasítás a teljes Customer objektum helyett a Name tulajdonságot adja vissza. Mivel Name sztringről van szó, a típus argumentuma custNameQuery nem stringCustomer.
  3. Mivel custNameQuery sztringsorozatról van szó, a foreach hurok iterációs változójának is egynek stringkell lennie.

Az alábbi ábrán egy valamivel összetettebb átalakítás látható. Az select utasítás egy névtelen típust ad vissza, amely az eredeti Customer objektumnak csak két tagját rögzíti.

Diagram showing a more complex query that transforms the data type.

  1. Az adatforrás típusargumentuma mindig a lekérdezés tartományváltozójának típusa.
  2. Mivel az select utasítás névtelen típust állít elő, a lekérdezési változót implicit módon kell begépelni a használatával var.
  3. Mivel a lekérdezési változó típusa implicit, a ciklus iterációs változójának foreach implicitnek is kell lennie.

A fordító típusadatainak következtetése

Bár ismernie kell a lekérdezési műveletek típuskapcsolatait, lehetősége van arra, hogy a fordító elvégezhesse az összes munkát. A kulcsszó var a lekérdezési művelet bármely helyi változója esetében használható. Az alábbi ábra hasonló a korábban tárgyalt 2. példához. A fordító azonban biztosítja az erős típust a lekérdezési művelet egyes változóihoz.

Diagram that shows the type flow with implicit typing.

LINQ és általános típusok (C#)

A LINQ-lekérdezések általános típusokon alapulnak. A lekérdezések írásához nincs szükség az általános adatok részletes ismeretére. Érdemes azonban két alapfogalmat is megismernie:

  1. Amikor egy általános gyűjteményosztály egy példányát hozza létre, például List<T>a "T" helyére a lista által tartandó objektumtípust írja be. A sztringek listája például a következőképpen van kifejezve List<string>, és az objektumok listája Customer a List<Customer>következőképpen van kifejezve. Az általános lista erősen gépelt, és számos előnnyel jár az elemeket Objecttároló gyűjteményekkel szemben. Ha megpróbál hozzáadni egy Customer újat, List<string>a fordításkor hibaüzenet jelenik meg. Az általános gyűjtemények használata egyszerű, mert nem kell futásidejű típus-öntést végeznie.
  2. IEnumerable<T> az a felület, amely lehetővé teszi az általános gyűjteményosztályok számbavételét az foreach utasítás használatával. Az általános gyűjteményosztályok ugyanúgy támogatják IEnumerable<T> a nem általános gyűjteményosztályokat, mint például a ArrayList támogatást IEnumerable.

Az általános szolgáltatásokkal kapcsolatos további információkért lásd: Generics.

IEnumerable<T> változók LINQ-lekérdezésekben

A LINQ lekérdezési változók a következőképpen vannak begépelve IEnumerable<T> , vagy származtatott típusként, például IQueryable<T>. Ha egy beírt IEnumerable<Customer>lekérdezési változót lát, az csak azt jelenti, hogy a lekérdezés végrehajtásakor nulla vagy több Customer objektum sorozata jön létre.

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

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

Általános típusdeklarációk kezelése a fordítóval

Ha szeretné, a var kulcsszóval elkerülheti az általános szintaxist. A var kulcsszó arra utasítja a fordítót, hogy a záradékban megadott adatforrás alapján következtetsen a lekérdezési változó típusára from . Az alábbi példa ugyanazt a lefordított kódot állítja elő, mint az előző példában:

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

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

A var kulcsszó akkor hasznos, ha a változó típusa nyilvánvaló, vagy ha nem olyan fontos explicit módon megadni a beágyazott általános típusokat, például a csoportos lekérdezések által előállítottakat. Általában azt javasoljuk, hogy ha használja var, ne feledje, hogy ez megnehezítheti a kód olvasását. További információ: Implicit módon beírt helyi változók.