Operazioni di proiezione

Aggiornamento: novembre 2007

La proiezione fa riferimento all'operazione di trasformazione di un oggetto in un nuovo form costituito spesso solo dalle proprietà che verranno utilizzate successivamente. Mediante l'utilizzo della proiezione è possibile costruire un nuovo tipo creato da ogni oggetto. È possibile proiettare una proprietà ed eseguirvi una funzione matematica. È inoltre possibile proiettare l'oggetto originale senza modificarlo.

I metodi degli operatori di query standard che eseguono la proiezione sono riportati nella sezione seguente.

Metodi

Nome metodo

Descrizione

Sintassi dell'espressione di query in C#

Sintassi dell'espressione di query in Visual Basic

Ulteriori informazioni

Select

Proietta i valori che si basano su una funzione di trasformazione.

select

Select

Enumerable.Select

Queryable.Select

SelectMany

Proietta le sequenze di valori che si basano su una funzione di trasformazione semplificandoli in un'unica sequenza.

Utilizzare più clausole from

Utilizzare più clausole From

Enumerable.SelectMany

Queryable.SelectMany

Esempi di sintassi dell'espressione di query

Select

Nell'esempio seguente viene utilizzata la clausola select in C# o la clausola Select in Visual Basic per proiettare la prima lettera di ogni stringa in un elenco di stringhe.

Dim words As New List(Of String)(New String() {"an", "apple", "a", "day"})

Dim query = From word In words _
            Select word.Substring(0, 1)

Dim sb As New System.Text.StringBuilder()
For Each letter As String In query
    sb.AppendLine(letter)
Next

' Display the output.
MsgBox(sb.ToString())

' This code produces the following output:

' a
' a
' a
' d
List<string> words = new List<string>() { "an", "apple", "a", "day" };

var query = from word in words
            select word.Substring(0, 1);

foreach (string s in query)
    Console.WriteLine(s);

/* This code produces the following output:

    a
    a
    a
    d
*/

SelectMany

Nell'esempio seguente vengono utilizzate più clausole from in C# o clausole From in Visual Basic per proiettare tutte le parole di ogni stringa in un elenco di stringhe.

Dim phrases As New List(Of String)(New String() {"an apple a day", "the quick brown fox"})

Dim query = From phrase In phrases _
            From word In phrase.Split(" "c) _
            Select word

Dim sb As New System.Text.StringBuilder()
For Each str As String In query
    sb.AppendLine(str)
Next

' Display the output.
MsgBox(sb.ToString())

' This code produces the following output:

' an
' apple
' a
' day
' the
' quick
' brown
' fox
List<string> phrases = new List<string>() { "an apple a day", "the quick brown fox" };

var query = from phrase in phrases
            from word in phrase.Split(' ')
            select word;

foreach (string s in query)
    Console.WriteLine(s);

/* This code produces the following output:

    an
    apple
    a
    day
    the
    quick
    brown
    fox
*/

Confronto tra Select e SelectMany

La funzione di Select() e SelectMany() è produrre un valore o più valori dai valori di origine. Select() produce un valore per ogni valore di origine. Il risultato complessivo è pertanto un insieme contenente lo stesso numero di elementi dell'insieme di origine. Al contrario, SelectMany() produce un singolo risultato complessivo che contiene sottoinsiemi concatenati di ogni valore di origine. La funzione di trasformazione passata come argomento a SelectMany() deve restituire una sequenza enumerabile di valori per ogni valore di origine. Queste sequenze enumerabili vengono quindi concatenate da SelectMany() per creare un'unica grande sequenza.

Nelle due illustrazioni seguenti viene mostrata la differenza basilare tra le azioni di questi due metodi. In ogni caso, si supponga che la funzione del selettore (trasformazione) selezioni la matrice di fiori di ogni valore di origine.

In questa figura viene illustrato come Select() restituisca un insieme contenente lo stesso numero di elementi dell'insieme di origine.

Illustrazione concettuale dell'azione di Select()

In questa figura viene illustrato come SelectMany() concateni la sequenza intermedia di matrici in un unico valore finale contenente tutti i valori di ogni matrice intermedia.

Grafica che mostra l'azione di SelectMany()

Esempio di codice

Nell'esempio seguente viene confrontato il comportamento di Select() e SelectMany(). Il codice crea un "bouquet" di fiori prendendo i primi due elementi di ogni elenco di nomi di fiori nell'insieme di origine. In questo esempio il "singolo valore" utilizzato dalla funzione di trasformazione Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>) è esso stesso un insieme di valori. Questo richiede il ciclo foreach aggiuntivo (For Each in Visual Basic) in modo da enumerare tutte le stringhe di ogni sottosequenza.

Class Bouquet
    Public Flowers As List(Of String)
End Class

Sub SelectVsSelectMany()
    Dim bouquets As New List(Of Bouquet)(New Bouquet() { _
        New Bouquet With {.Flowers = New List(Of String)(New String() {"sunflower", "daisy", "daffodil", "larkspur"})}, _
        New Bouquet With {.Flowers = New List(Of String)(New String() {"tulip", "rose", "orchid"})}, _
        New Bouquet With {.Flowers = New List(Of String)(New String() {"gladiolis", "lily", "snapdragon", "aster", "protea"})}, _
        New Bouquet With {.Flowers = New List(Of String)(New String() {"larkspur", "lilac", "iris", "dahlia"})}})

    Dim output As New System.Text.StringBuilder

    ' Select()
    Dim query1 = bouquets.Select(Function(b) b.Flowers)

    output.AppendLine("Using Select():")
    For Each flowerList In query1
        For Each str As String In flowerList
            output.AppendLine(str)
        Next
    Next

    ' SelectMany()
    Dim query2 = bouquets.SelectMany(Function(b) b.Flowers)

    output.AppendLine(vbCrLf & "Using SelectMany():")
    For Each str As String In query2
        output.AppendLine(str)
    Next

    ' Display the output
    MsgBox(output.ToString())

    ' This code produces the following output:
    '
    ' Using Select():
    ' sunflower
    ' daisy
    ' daffodil
    ' larkspur
    ' tulip
    ' rose
    ' orchid
    ' gladiolis
    ' lily
    ' snapdragon
    ' aster
    ' protea
    ' larkspur
    ' lilac
    ' iris
    ' dahlia

    ' Using SelectMany()
    ' sunflower
    ' daisy
    ' daffodil
    ' larkspur
    ' tulip
    ' rose
    ' orchid
    ' gladiolis
    ' lily
    ' snapdragon
    ' aster
    ' protea
    ' larkspur
    ' lilac
    ' iris
    ' dahlia

End Sub
class Bouquet
{
    public List<string> Flowers { get; set; }
}

static void SelectVsSelectMany()
{
    List<Bouquet> bouquets = new List<Bouquet>() {
        new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }},
        new Bouquet{ Flowers = new List<string> { "tulip", "rose", "orchid" }},
        new Bouquet{ Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }},
        new Bouquet{ Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }}
    };

    // *********** Select ***********            
    IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);

    // ********* SelectMany *********
    IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers);

    Console.WriteLine("Results by using Select():");
    // Note the extra foreach loop here.
    foreach (IEnumerable<String> collection in query1)
        foreach (string item in collection)
            Console.WriteLine(item);

    Console.WriteLine("\nResults by using SelectMany():");
    foreach (string item in query2)
        Console.WriteLine(item);

    /* This code produces the following output:

       Results by using Select():
        sunflower
        daisy
        daffodil
        larkspur
        tulip
        rose
        orchid
        gladiolis
        lily
        snapdragon
        aster
        protea
        larkspur
        lilac
        iris
        dahlia

       Results by using SelectMany():
        sunflower
        daisy
        daffodil
        larkspur
        tulip
        rose
        orchid
        gladiolis
        lily
        snapdragon
        aster
        protea
        larkspur
        lilac
        iris
        dahlia
    */

}

Ulteriori informazioni sulla proiezione

Vedere anche

Concetti

Cenni preliminari sugli operatori di query standard

Riferimenti

Clausola select (Riferimento C#)

Clausola Select (Visual Basic)

System.Linq