Sdílet prostřednictvím


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 numselect 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í.

Viz také