Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La projection fait référence à l’opération de transformation d’un objet en une nouvelle forme qui se compose souvent de ces propriétés utilisées par la suite. À l’aide de la projection, vous pouvez construire un nouveau type généré à partir de chaque objet. Vous pouvez projeter une propriété et y effectuer une fonction mathématique. Vous pouvez également projeter l’objet d’origine sans le modifier.
Importante
Ces exemples utilisent une source de données System.Collections.Generic.IEnumerable<T>. Les sources de données basées sur System.Linq.IQueryProvider utilisent des sources de données System.Linq.IQueryable<T> et des arborescences d’expressions. Les arborescences d’expressions présentent des limitations sur la syntaxe C# autorisée. De plus, chaque source de données IQueryProvider
, telle que EF Core peut imposer des restrictions supplémentaires. Consultez la documentation de votre source de données.
Les méthodes d’opérateur de requête standard qui effectuent une projection sont répertoriées dans la section suivante.
Méthodes
Noms de méthode | Descriptif | Syntaxe d’expression de requête C# | Plus d’informations |
---|---|---|---|
Sélectionnez | Projette des valeurs qui sont basées sur une fonction de transformation. | select |
Enumerable.Select Queryable.Select |
SelectMany | Projette des séquences de valeurs basées sur une fonction de transformation, puis les aplatit en une seule séquence. | Utiliser plusieurs from clauses |
Enumerable.SelectMany Queryable.SelectMany |
Code postal | Produit une séquence de tuples dont les éléments proviennent de 2 ou 3 séquences spécifiées. | Non applicable. | Enumerable.Zip Queryable.Zip |
Select
L’exemple suivant utilise la select
clause pour projeter la première lettre de chaque chaîne dans une liste de chaînes.
List<string> words = ["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
*/
La requête équivalente utilisant la syntaxe de méthode est illustrée dans le code suivant :
List<string> words = ["an", "apple", "a", "day"];
var query = words.Select(word => word.Substring(0, 1));
foreach (string s in query)
{
Console.WriteLine(s);
}
/* This code produces the following output:
a
a
a
d
*/
SelectMany
L’exemple suivant utilise plusieurs from
clauses pour projeter chaque mot de chaque chaîne dans une liste de chaînes.
List<string> phrases = ["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
*/
La requête équivalente utilisant la syntaxe de méthode est illustrée dans le code suivant :
List<string> phrases = ["an apple a day", "the quick brown fox"];
var query = phrases.SelectMany(phrase => phrase.Split(' '));
foreach (string s in query)
{
Console.WriteLine(s);
}
/* This code produces the following output:
an
apple
a
day
the
quick
brown
fox
*/
La SelectMany
méthode peut également former la combinaison de correspondances entre chaque élément de la première séquence et chaque élément de la deuxième séquence :
var query = from number in numbers
from letter in letters
select (number, letter);
foreach (var item in query)
{
Console.WriteLine(item);
}
La requête équivalente utilisant la syntaxe de méthode est illustrée dans le code suivant :
var method = numbers
.SelectMany(number => letters,
(number, letter) => (number, letter));
foreach (var item in method)
{
Console.WriteLine(item);
}
Zip
Il existe plusieurs surcharges pour l’opérateur de projection Zip
. Toutes les Zip
méthodes fonctionnent sur des séquences de deux types ou plus potentiellement hétérogènes. Les deux premières surcharges retournent des tuples, avec le type positionnel correspondant à partir des séquences données.
Tenez compte des collections suivantes :
// An int array with 7 elements.
IEnumerable<int> numbers = [1, 2, 3, 4, 5, 6, 7];
// A char array with 6 elements.
IEnumerable<char> letters = ['A', 'B', 'C', 'D', 'E', 'F'];
Pour projeter ces séquences ensemble, utilisez l’opérateur Enumerable.Zip<TFirst,TSecond>(IEnumerable<TFirst>, IEnumerable<TSecond>) :
foreach ((int number, char letter) in numbers.Zip(letters))
{
Console.WriteLine($"Number: {number} zipped with letter: '{letter}'");
}
// This code produces the following output:
// Number: 1 zipped with letter: 'A'
// Number: 2 zipped with letter: 'B'
// Number: 3 zipped with letter: 'C'
// Number: 4 zipped with letter: 'D'
// Number: 5 zipped with letter: 'E'
// Number: 6 zipped with letter: 'F'
Importante
La séquence résultante d’une opération zip n’est jamais plus longue que la séquence la plus courte. Les collections numbers
et letters
diffèrent par leur longueur, et la séquence qui en résulte omet le dernier élément de la collection numbers
, car il n’a rien à compresser.
La deuxième surcharge accepte une séquence third
. Nous allons créer une autre collection, à savoir emoji
:
// A string array with 8 elements.
IEnumerable<string> emoji = [ "🤓", "🔥", "🎉", "👀", "⭐", "💜", "✔", "💯"];
Pour projeter ces séquences ensemble, utilisez l’opérateur Enumerable.Zip<TFirst,TSecond,TThird>(IEnumerable<TFirst>, IEnumerable<TSecond>, IEnumerable<TThird>) :
foreach ((int number, char letter, string em) in numbers.Zip(letters, emoji))
{
Console.WriteLine(
$"Number: {number} is zipped with letter: '{letter}' and emoji: {em}");
}
// This code produces the following output:
// Number: 1 is zipped with letter: 'A' and emoji: 🤓
// Number: 2 is zipped with letter: 'B' and emoji: 🔥
// Number: 3 is zipped with letter: 'C' and emoji: 🎉
// Number: 4 is zipped with letter: 'D' and emoji: 👀
// Number: 5 is zipped with letter: 'E' and emoji: ⭐
// Number: 6 is zipped with letter: 'F' and emoji: 💜
Tout comme la surcharge précédente, la Zip
méthode projette un tuple, mais cette fois avec trois éléments.
La troisième surcharge accepte un Func<TFirst, TSecond, TResult>
argument qui agit comme sélecteur de résultats. Vous pouvez projeter une nouvelle séquence résultante à partir des séquences compressées.
foreach (string result in
numbers.Zip(letters, (number, letter) => $"{number} = {letter} ({(int)letter})"))
{
Console.WriteLine(result);
}
// This code produces the following output:
// 1 = A (65)
// 2 = B (66)
// 3 = C (67)
// 4 = D (68)
// 5 = E (69)
// 6 = F (70)
Avec la surcharge précédente Zip
, la fonction spécifiée est appliquée sur les éléments number
et letter
, ce qui génère une séquence des résultats string
.
Select
contre SelectMany
Le travail des deux Select
et SelectMany
consiste à produire une valeur de résultat (ou des valeurs) à partir de valeurs sources.
Select
produit une valeur de résultat pour chaque valeur source. Le résultat global est donc une collection qui a le même nombre d’éléments que la collection source. En revanche, SelectMany
produit un résultat global unique qui contient des sous-collections concaténées à partir de chaque valeur source. La fonction de transformation qui est passée en tant qu'argument à SelectMany
doit retourner une séquence énumérable de valeurs pour chaque valeur source.
SelectMany
concatène ces séquences énumérables pour créer une séquence volumineuse.
Les deux illustrations suivantes montrent la différence conceptuelle entre les actions de ces deux méthodes. Dans chaque cas, supposons que la fonction (de transformation) du sélecteur sélectionne le tableau de fleurs (Flowers) à partir de chaque valeur source.
Cette illustration montre comment Select
retourne une collection qui a le même nombre d’éléments que la collection source.
Cette illustration montre comment SelectMany
concaténer la séquence intermédiaire de tableaux en une valeur de résultat finale qui contient chaque valeur de chaque tableau intermédiaire.
Exemple de code
L’exemple suivant compare le comportement de Select
et SelectMany
. Le code crée un « bouquet » de fleurs en prenant les éléments de chaque liste de noms de fleurs dans la collection source. Dans l’exemple suivant, la « valeur unique » utilisée par la fonction Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>) de transformation est une collection de valeurs. Cet exemple nécessite la boucle supplémentaire foreach
afin d’énumérer chaque chaîne dans chaque sous-séquence.
class Bouquet
{
public required List<string> Flowers { get; init; }
}
static void SelectVsSelectMany()
{
List<Bouquet> bouquets =
[
new Bouquet { Flowers = ["sunflower", "daisy", "daffodil", "larkspur"] },
new Bouquet { Flowers = ["tulip", "rose", "orchid"] },
new Bouquet { Flowers = ["gladiolis", "lily", "snapdragon", "aster", "protea"] },
new Bouquet { Flowers = ["larkspur", "lilac", "iris", "dahlia"] }
];
IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);
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);
}
}