from clause (Referenční dokumentace jazyka C#)
Výraz dotazu musí začínat klauzulí from
. Kromě toho výraz dotazu může obsahovat dílčí dotazy, které také začínají klauzulí from
. Klauzule from
určuje následující:
Zdroj dat, na kterém se bude dotaz nebo dílčí dotaz spouštět.
Místní proměnná rozsahu , která představuje každý prvek ve zdrojové sekvenci.
Proměnná rozsahu i zdroj dat jsou silného typu. Zdroj dat odkazovaný v from
klauzuli musí mít typ IEnumerable, IEnumerable<T>nebo odvozený typ, například IQueryable<T>.
V následujícím příkladu numbers
je zdrojem dat a num
jedná se o proměnnou rozsahu. Všimněte si, že obě proměnné jsou silného typu, i když se používá klíčové slovo var .
class LowNums
{
static void Main()
{
// A simple data source.
int[] numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
// Create the query.
// lowNums is an IEnumerable<int>
var lowNums = from num in numbers
where num < 5
select num;
// Execute the query.
foreach (int i in lowNums)
{
Console.Write(i + " ");
}
}
}
// Output: 4 1 3 2 0
Proměnná rozsahu
Kompilátor odvodí typ proměnné rozsahu při implementaci IEnumerable<T>zdroje dat . Pokud má zdroj například typ IEnumerable<Customer>
, pak proměnná rozsahu je odvozena tak, aby byla Customer
. Jediný čas, kdy je nutné zadat typ explicitně, je, když je zdrojem jiný než obecný IEnumerable
typ, například ArrayList. Další informace naleznete v tématu Jak dotazovat ArrayList pomocí LINQ.
V předchozím příkladu num
je odvozen jako typ int
. Vzhledem k tomu, že proměnná rozsahu je silně typovaná, můžete ji volat nebo ji použít v jiných operacích. Místo psaní můžete například napsatselect num
select num.ToString()
, aby výraz dotazu vrátil posloupnost řetězců místo celých čísel. Nebo můžete napsat select num + 10
, aby výraz vrátil sekvenci 14, 11, 13, 12, 10. Další informace najdete v klauzuli select.
Proměnná rozsahu je jako iterační proměnná v příkazu foreach s výjimkou jednoho velmi důležitého rozdílu: proměnná rozsahu nikdy ve skutečnosti neuchová data ze zdroje. Je to jen syntaktické pohodlí, které umožňuje dotazu popsat, co se stane při spuštění dotazu. Další informace najdete v tématu Úvod k dotazům LINQ (C#).
Složené z klauzulí
V některýchpřípadechch Zdrojem dat může být IEnumerable<Student>
například umístění, ve kterém každý objekt studenta v sekvenci obsahuje seznam výsledků testů. Pro přístup k vnitřnímu seznamu v rámci každého Student
prvku můžete použít složené from
klauzule. Tato technika se podobá použití vnořených příkazů foreach . Můžete přidat klauzule where nebo orderby do některé from
z klauzulí pro filtrování výsledků. Následující příklad ukazuje posloupnost Student
objektů, z nichž každá obsahuje vnitřní List
celá čísla představující skóre testu. Pro přístup k vnitřnímu seznamu použijte složenou from
klauzuli. V případě potřeby můžete mezi dvě from
klauzule vložit klauzule.
class CompoundFrom
{
// The element type of the data source.
public class Student
{
public required string LastName { get; init; }
public required List<int> Scores {get; init;}
}
static void Main()
{
// Use a collection initializer to create the data source. Note that
// each element in the list contains an inner sequence of scores.
List<Student> students =
[
new Student {LastName="Omelchenko", Scores= [97, 72, 81, 60]},
new Student {LastName="O'Donnell", Scores= [75, 84, 91, 39]},
new Student {LastName="Mortensen", Scores= [88, 94, 65, 85]},
new Student {LastName="Garcia", Scores= [97, 89, 85, 82]},
new Student {LastName="Beebe", Scores= [35, 72, 91, 70]}
];
// Use a compound from to access the inner sequence within each element.
// Note the similarity to a nested foreach statement.
var scoreQuery = from student in students
from score in student.Scores
where score > 90
select new { Last = student.LastName, score };
// Execute the queries.
Console.WriteLine("scoreQuery:");
// Rest the mouse pointer on scoreQuery in the following line to
// see its type. The type is IEnumerable<'a>, where 'a is an
// anonymous type defined as new {string Last, int score}. That is,
// each instance of this anonymous type has two members, a string
// (Last) and an int (score).
foreach (var student in scoreQuery)
{
Console.WriteLine("{0} Score: {1}", student.Last, student.score);
}
}
}
/*
scoreQuery:
Omelchenko Score: 97
O'Donnell Score: 91
Mortensen Score: 94
Garcia Score: 97
Beebe Score: 91
*/
Použití více z klauzulí k provedení spojení
Složená from
klauzule se používá pro přístup k vnitřním kolekcí v jednom zdroji dat. Dotaz však může obsahovat také více from
klauzulí, které generují doplňkové dotazy z nezávislých zdrojů dat. Tato technika umožňuje provádět určité typy operací spojení, které nejsou možné pomocí klauzule join.
Následující příklad ukazuje, jak lze použít dvě from
klauzule k vytvoření kompletního křížového spojení dvou zdrojů dat.
class CompoundFrom2
{
static void Main()
{
char[] upperCase = ['A', 'B', 'C'];
char[] lowerCase = ['x', 'y', 'z'];
// The type of joinQuery1 is IEnumerable<'a>, where 'a
// indicates an anonymous type. This anonymous type has two
// members, upper and lower, both of type char.
var joinQuery1 =
from upper in upperCase
from lower in lowerCase
select new { upper, lower };
// The type of joinQuery2 is IEnumerable<'a>, where 'a
// indicates an anonymous type. This anonymous type has two
// members, upper and lower, both of type char.
var joinQuery2 =
from lower in lowerCase
where lower != 'x'
from upper in upperCase
select new { lower, upper };
// Execute the queries.
Console.WriteLine("Cross join:");
// Rest the mouse pointer on joinQuery1 to verify its type.
foreach (var pair in joinQuery1)
{
Console.WriteLine("{0} is matched to {1}", pair.upper, pair.lower);
}
Console.WriteLine("Filtered non-equijoin:");
// Rest the mouse pointer over joinQuery2 to verify its type.
foreach (var pair in joinQuery2)
{
Console.WriteLine("{0} is matched to {1}", pair.lower, pair.upper);
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Cross join:
A is matched to x
A is matched to y
A is matched to z
B is matched to x
B is matched to y
B is matched to z
C is matched to x
C is matched to y
C is matched to z
Filtered non-equijoin:
y is matched to A
y is matched to B
y is matched to C
z is matched to A
z is matched to B
z is matched to C
*/
Další informace o operacích spojení, které používají více from
klauzulí, naleznete v tématu Provedení levých vnějších spojení.