Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Proyeksi mengacu pada operasi mengubah objek menjadi bentuk baru yang sering hanya terdiri dari properti tersebut yang kemudian digunakan. Dengan menggunakan proyeksi, Anda dapat membuat jenis baru yang dibangun dari setiap objek. Anda dapat memproyeksikan properti dan melakukan fungsi matematika di atasnya. Anda juga dapat memproyekan objek asli tanpa mengubahnya.
Penting
Sampel ini menggunakan System.Collections.Generic.IEnumerable<T> sumber data. Sumber data berdasarkan System.Linq.IQueryProvider penggunaan System.Linq.IQueryable<T> sumber data dan pohon ekspresi. Pohon ekspresi memiliki batasan pada sintaks C# yang diizinkan. Selain itu, setiap IQueryProvider
sumber data, seperti EF Core dapat memberlakukan lebih banyak batasan. Periksa dokumentasi untuk sumber data Anda.
Metode operator kueri standar yang melakukan proyeksi tercantum di bagian berikut.
Metode
Nama metode | Deskripsi | Sintaks kueri ekspresi C# | Informasi selengkapnya |
---|---|---|---|
Pilih | Memproyeksikan nilai yang didasarkan pada fungsi transformasi. | select |
Enumerable.Select Queryable.Select |
Pilih Banyak | Memproyeksikan urutan nilai yang didasarkan pada fungsi transformasi dan kemudian meratakannya menjadi satu urutan. | Menggunakan beberapa from klausa |
Enumerable.SelectMany Queryable.SelectMany |
Zip | Menghasilkan serangkaian tuple dengan elemen-elemen dari 2-3 urutan yang ditentukan. | Tidak dapat diterapkan. | Enumerable.Zip Queryable.Zip |
Select
Contoh berikut menggunakan klausul select
untuk memproyeksikan huruf pertama dari setiap string dalam daftar string.
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
*/
Kueri yang setara menggunakan sintaks metode diperlihatkan dalam kode berikut:
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
Contoh berikut menggunakan beberapa from
klausa untuk memproyeksikan setiap kata dari setiap string dalam daftar string.
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
*/
Kueri yang setara menggunakan sintaks metode diperlihatkan dalam kode berikut:
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
*/
Metode ini SelectMany
juga dapat membentuk kombinasi pencocokan setiap item dalam urutan pertama dengan setiap item dalam urutan kedua:
var query = from number in numbers
from letter in letters
select (number, letter);
foreach (var item in query)
{
Console.WriteLine(item);
}
Kueri yang setara menggunakan sintaks metode diperlihatkan dalam kode berikut:
var method = numbers
.SelectMany(number => letters,
(number, letter) => (number, letter));
foreach (var item in method)
{
Console.WriteLine(item);
}
Zip
Ada beberapa kelebihan beban untuk Zip
operator proyeksi. Semua metode Zip
bekerja untuk urutan yang terdiri dari dua atau lebih tipe yang mungkin heterogen. Dua kelebihan beban pertama mengembalikan tuple, dengan jenis posisi yang sesuai dari urutan yang diberikan.
Pertimbangkan koleksi berikut:
// 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'];
Untuk memproyekan urutan ini bersama-sama, gunakan Enumerable.Zip<TFirst,TSecond>(IEnumerable<TFirst>, IEnumerable<TSecond>) operator:
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'
Penting
Urutan yang dihasilkan dari operasi zip tidak pernah panjangnya lebih panjang daripada urutan terpendek. Panjang numbers
koleksi dan letters
berbeda, dan urutan yang dihasilkan menghilangkan elemen terakhir dari numbers
koleksi, karena tidak memiliki apa pun untuk di-zip.
Kelebihan beban kedua menerima third
urutan. Mari kita buat koleksi lain, yaitu emoji
:
// A string array with 8 elements.
IEnumerable<string> emoji = [ "🤓", "🔥", "🎉", "👀", "⭐", "💜", "✔", "💯"];
Untuk memproyekan urutan ini bersama-sama, gunakan Enumerable.Zip<TFirst,TSecond,TThird>(IEnumerable<TFirst>, IEnumerable<TSecond>, IEnumerable<TThird>) operator:
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: 💜
Sama seperti kelebihan beban sebelumnya, metode ini Zip
memproyeksikan tuple, tetapi kali ini dengan tiga elemen.
Fungsi overload ketiga menerima argumen Func<TFirst, TSecond, TResult>
yang bertindak sebagai selektor hasil. Anda dapat memproyekikan urutan hasil baru dari urutan yang di-zip.
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)
Dengan kelebihan beban sebelumnya Zip
, fungsi yang ditentukan diterapkan ke elemen number
yang sesuai dan letter
, menghasilkan urutan hasil string
.
Select
melawan SelectMany
Pekerjaan keduanya Select
dan SelectMany
adalah menghasilkan nilai hasil (atau nilai) dari nilai sumber.
Select
menghasilkan satu nilai hasil untuk setiap nilai sumber. Oleh karena itu, hasil keseluruhan adalah koleksi yang memiliki jumlah elemen yang sama dengan koleksi sumber. Sebaliknya, SelectMany
menghasilkan satu hasil keseluruhan yang berisi subkoleksi yang digabungkan dari setiap nilai sumber. Fungsi transformasi yang diteruskan sebagai argumen ke SelectMany
harus mengembalikan urutan nilai yang enumerable untuk setiap nilai sumber.
SelectMany
menggabungkan urutan yang dapat dijumlahkan ini untuk membuat satu urutan besar.
Dua ilustrasi berikut menunjukkan perbedaan konseptual antara tindakan kedua metode ini. Dalam setiap kasus, asumsikan bahwa fungsi pemilih (transform) memilih array bunga dari setiap nilai sumber.
Ilustrasi ini menggambarkan bagaimana Select
mengembalikan koleksi yang memiliki jumlah elemen yang sama dengan kumpulan sumber.
Ilustrasi ini menggambarkan bagaimana SelectMany
menggabungkan urutan perantara array menjadi satu nilai hasil akhir yang berisi setiap nilai dari setiap array perantara.
Contoh kode
Contoh berikut membandingkan perilaku Select
dan SelectMany
. Kode ini membuat "buket" bunga dengan mengambil item dari setiap daftar nama bunga dalam koleksi sumber. Dalam contoh berikut, "nilai tunggal" yang digunakan fungsi Select<TSource,TResult>(IEnumerable<TSource>, Func<TSource,TResult>) transformasi adalah kumpulan nilai. Contoh ini memerlukan perulangan tambahan foreach
untuk menghitung setiap string di setiap urutan berikutnya.
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);
}
}