from-sats (C#-referens)

Ett frågeuttryck måste börja med en from sats. Dessutom kan ett frågeuttryck innehålla underfrågor, som också börjar med en from sats. Satsen from anger följande:

  • Datakällan där frågan eller underfrågan ska köras.

  • En lokal intervallvariabel som representerar varje element i källsekvensen.

Både intervallvariabeln och datakällan skrivs starkt. Datakällan som refereras i from -satsen måste ha en typ av IEnumerable, IEnumerable<T>eller en härledd typ som IQueryable<T>.

I följande exempel numbers är datakällan och num intervallvariabeln. Observera att båda variablerna är starkt skrivna trots att nyckelordet var används.

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

Intervallvariabeln

Kompilatorn härleder typen av intervallvariabel när datakällan implementerar IEnumerable<T>. Om källan till exempel har en typ av IEnumerable<Customer>, kommer intervallvariabeln att härledas Customertill . Den enda gången du måste ange typen explicit är när källan är en icke-generisk IEnumerable typ, till exempel ArrayList. Mer information finns i Köra frågor mot en matrislista med LINQ.

I föregående exempel num härleds att vara av typen int. Eftersom intervallvariabeln är starkt skriven kan du anropa metoder på den eller använda den i andra åtgärder. I stället för att skriva kan du till exempel skriva select numselect num.ToString() så att frågeuttrycket returnerar en sekvens med strängar i stället för heltal. Eller så kan du skriva select num + 10 så att uttrycket returnerar sekvensen 14, 11, 13, 12, 10. Mer information finns i select-sats.

Intervallvariabeln är som en iterationsvariabel i en foreach-instruktion förutom en mycket viktig skillnad: en intervallvariabel lagrar aldrig data från källan. Det är bara en syntaktisk bekvämlighet som gör att frågan kan beskriva vad som händer när frågan körs. Mer information finns i Introduktion till LINQ-frågor (C#).

Sammansatt från satser

I vissa fall kan varje element i källsekvensen vara antingen en sekvens eller innehålla en sekvens. Datakällan kan till exempel vara en IEnumerable<Student> plats där varje elevobjekt i sekvensen innehåller en lista med testresultat. Om du vill komma åt den inre listan i varje Student element kan du använda sammansatta from satser. Tekniken är som att använda kapslade foreach-instruktioner . Du kan lägga till where - eller orderby-satser i endera from satsen för att filtrera resultatet. I följande exempel visas en sekvens med Student objekt som var och en innehåller ett inre List heltal som representerar testresultat. Använd en sammansatt from sats för att komma åt den inre listan. Du kan infoga satser mellan de två from satserna om det behövs.

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
*/

Använda flera från satser för att utföra kopplingar

En sammansatt from sats används för att komma åt inre samlingar i en enda datakälla. En fråga kan dock också innehålla flera from satser som genererar kompletterande frågor från oberoende datakällor. Med den här tekniken kan du utföra vissa typer av kopplingsåtgärder som inte är möjliga med hjälp av kopplingssatsen.

I följande exempel visas hur två from satser kan användas för att skapa en fullständig korskoppling av två datakällor.

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
        */

Mer information om kopplingsåtgärder som använder flera from satser finns i Utföra yttre kopplingar till vänster.

Se även