Hasil kueri jarang membutuhkan seluruh isi object. Laporan harga biasanya hanya memerlukan nama dan angka tertentu, sedangkan property lain justru menambah kebisingan. Operator Select membentuk ulang setiap elemen: satu elemen sumber menghasilkan satu elemen hasil dengan bentuk yang kita tentukan sendiri.

Mengubah Bentuk Elemen #

Contoh berikut memproyeksikan setiap produk menjadi nama beserta harga naik sebesar Rp5000:

csharp
record Produk(string Nama, string Kategori, int Harga, int Stok);

List<Produk> produk = new()
{
    new Produk("Kopi Gayo", "Minuman", 25000, 40),
    new Produk("Teh Melati", "Minuman", 15000, 60),
    new Produk("Roti Bakar", "Makanan", 12000, 25),
    new Produk("Susu UHT", "Minuman", 20000, 35),
    new Produk("Keripik Singkong", "Makanan", 10000, 80)
};

var hargaBaru = produk.Select(p => new { p.Nama, HargaNaik = p.Harga + 5000 });

foreach (var p in hargaBaru)
{
    Console.WriteLine($"{p.Nama}: {p.HargaNaik}");
}

Output yang Dihasilkan:

text
Kopi Gayo: 30000
Teh Melati: 20000
Roti Bakar: 17000
Susu UHT: 25000
Keripik Singkong: 15000

Mari kita bedah baris demi baris:

  1. produk.Select(...): operator projection diterapkan pada setiap elemen Produk, satu per satu.
  2. new { p.Nama, HargaNaik = p.Harga + 5000 }: anonymous type dengan dua field; p.Nama memakai nama property asli, dan HargaNaik diberi nama eksplisit.
  3. foreach (var p in hargaBaru): kata var dipakai karena tipe hasil dibangkitkan compiler dan tidak dideklarasikan secara manual.
  4. jumlah elemen: lima produk masuk, lima hasil keluar; Select tidak menyaring ataupun mengurutkan apa pun.

Hasil Projection Berbentuk Baru #

Tipe hasil berbeda dari tipe sumber: kueri di atas menghasilkan urutan anonymous type, bukan urutan Produk. Projection juga boleh menghasilkan satu property saja (p.Nama) maupun object record yang sudah ada sebelumnya. Karena tidak ada elemen yang dibuang, jumlah hasil selalu sama dengan jumlah sumber.

Mirip dengan Where, Select menyediakan overload berindeks: produk.Select((p, indeks) => $"{indeks}: {p.Nama}") menyertakan posisi elemen pada hasil. Untuk hasil bertingkat, kata kunci SelectMany meratakan kumpulan di dalam elemen menjadi satu urutan datar; operator ini biasanya baru diperlukan setelah kita terbiasa dengan Select biasa.

Dalam query expression, projection ini ditulis sebagai klausa terakhir, misalnya select new { p.Nama, HargaNaik = p.Harga + 5000 }. Bab Ordering selanjutnya menata urutan elemen hasil projection.