Tuple dan Dekonstruksi

Nilai kembali multi-nilai yang ringan.

Daftar isi

Topik ini membahas tuple dan deconstruction (dekonstruksi), yakni pembongkaran satu nilai gabungan ke beberapa variabel. Tuple diperkenalkan pada C# 7 sebagai nilai kembali multi-nilai yang ringan, sedangkan dekonstruksi adalah sintaks yang mengambil isi tuple atau tipe lain ke dalam variabel terpisah dalam satu pernyataan. Setelah topik ini diselesaikan, metode yang mengembalikan dua nilai dapat ditulis tanpa kelas pembungkus, dan isi data gabungan dapat dibongkar sesuai kebutuhan.

Tuple sebagai nilai kembali#

Metode yang mengembalikan lebih dari satu nilai dahulu harus memilih antara parameter out, kelas pembungkus, atau array yang maknanya samar. Tuple menyelesaikan persoalan itu dengan tipe yang menampung beberapa nilai dalam satu wadah bernama ValueTuple, yaitu struct (value type) yang ditangani sebagai nilai dan murah dibuat. Tipe kembaliannya ditulis seperti daftar tipe di dalam tanda kurung, dan nama elemen boleh disertakan agar maknanya terbaca langsung pada tanda tangan metode.

csharp Program.cs
// Program: tuple sebagai nilai kembali multi-nilai dan dekonstruksinya.
(int Terendah, int Tertinggi) Rentang(int[] nilai)
{
    int terendah = nilai[0];
    int tertinggi = nilai[0];

    foreach (int n in nilai)
    {
        if (n < terendah) terendah = n;
        if (n > tertinggi) tertinggi = n;
    }

    return (terendah, tertinggi);
}

var (terendah, tertinggi) = Rentang(new[] { 72, 85, 90, 68, 78 });
Console.WriteLine($"{terendah} sampai {tertinggi}");

var statistik = (Judul: "Penghitung Kata", JumlahBaris: 40);
Console.WriteLine($"{statistik.Judul} berisi {statistik.JumlahBaris} baris");

var (judul, _) = statistik;
Console.WriteLine(judul);

int a = 3;
int b = 8;
(a, b) = (b, a);
Console.WriteLine($"{a} {b}");

var titik = new Titik(2, 3);
var (x, y) = titik;
Console.WriteLine($"{x}, {y}");

record Titik(int X, int Y);
text Keluaran
68 sampai 90
Penghitung Kata berisi 40 baris
Penghitung Kata
8 3
2, 3

Metode Rentang mengembalikan (int Terendah, int Tertinggi), dan pernyataan return (terendah, tertinggi); membentuk tuple dari dua variabel lokal. Pemanggilnya langsung mendekonstruksi hasilnya menjadi dua variabel terendah dan tertinggi, sehingga tidak ada variabel penengah yang hanya dipakai sekali. Perhitungan pada program menghasilkan 68 sampai 90, dan kedua nama elemen Terendah serta Tertinggi langsung terbaca pada kode pemanggilnya.

Elemen bernama dan dekonstruksi#

Tuple literal boleh diberi nama elemen langsung pada pembuatannya, sebagaimana statistik yang menyimpan Judul dan JumlahBaris. Nama tersebut membuat aksesnya terbaca seperti property, yaitu statistik.Judul, tanpa mengubah sifat tuple yang tetap berupa sepasang nilai. Nama elemen dikelola oleh kompilator (compiler), program yang menerjemahkan kode sumber menjadi program yang dapat dieksekusi, sehingga tuple dengan nama berbeda tetap saling ditukar selama urutan tipenya cocok.

Dekonstruksi var (judul, _) = statistik; membongkar tuple menjadi variabel terpisah, dan tanda garis bawah _ berperan sebagai discard, yaitu penanda tempat yang sengaja tidak dibaca. Variabel hasil dekonstruksi bebas dinamai ulang karena nama elemen aslinya tidak terikat pada tipe runtime. Pernyataan (a, b) = (b, a); memperlihatkan bentuk lain, yaitu dekonstruksi ke variabel yang sudah ada tanpa var, sehingga pertukaran dua nilai terjadi dalam satu baris tanpa variabel bantu.

Elemen tuple tidak wajib bertipe sama, sehingga (int Nomer, string Nama) menyimpan pasangan nomor urut dan nama dalam satu wadah. Tipe campuran seperti ini sering muncul pada hasil penguraian baris data, misalnya nomor antrean beserta nama pemanggilnya, dan dekonstruksinya tetap mengikuti urutan tipe yang dideklarasikan. Nilai setiap elemen kemudian dibaca dengan tipe yang benar tanpa konversi manual, karena informasi tipenya tersimpan pada deklarasi tuple-nya.

Dekonstruksi pada tipe lain#

Dekonstruksi tidak terbatas pada tuple. Record posisional otomatis memperoleh metode Deconstruct, sehingga var (x, y) = titik; pada program di atas membongkar record Titik menjadi dua variabel dengan benar. Mekanisme yang sama dapat ditambahkan ke tipe apa pun melalui metode Deconstruct dengan parameter out, baik ditulis di dalam tipe maupun sebagai metode perluasan (extension method) untuk tipe pihak lain yang tidak boleh disunting. Parameternya dideklarasikan dengan out sebanyak nilai yang dihasilkan, dan urutannya menentukan urutan variabel sasaran dekonstruksi.

Kapan tuple dipilih#

Tuple paling tepat untuk nilai kembali yang sementara, terbatas dua sampai tiga elemen, dan tidak pernah disimpan lama di dalam program. Pengembalian dua hasil perhitungan ke pemanggil, penyampaian pasangan indeks dan nilai, serta pertukaran nilai cepat termasuk penggunaan yang sehat. Apabila data akan dilempar antar batas (boundary) program, disimpan dalam koleksi, atau membawa perilaku, tipe bernama seperti record lebih tepat karena namanya mendokumentasikan maksud dan anggotanya dapat dikembangkan.

Nama elemen pada tanda tangan metode perlu ditulis karena tuple yang kembali tanpa nama tetap sah secara tipe, tetapi membaca hasilnya menjadi bergantung pada posisi. Deklarasi (int, int) Rentang(...) tanpa nama tetap berjalan, sedangkan versi bernama memberikan dokumentasi tanpa upaya tambahan pada setiap pemanggilan. Kebiasaan yang baik adalah menamai elemen pada setiap tipe kembalian tuple yang ditulis sendiri.

Kesalahan umum#

  • Mengira nama elemen bagian dari tipe saat runtime. Nama seperti Terendah hanya dikenali kompilator, dan dua tuple bertipe (int, int) tetap saling ditukar meskipun namanya berbeda. Jangan mengandalkan nama untuk logika, melainkan gunakan nama sebagai dokumentasi.
  • Menumpuk banyak nilai dalam satu tuple. Tuple dengan lima elemen atau lebih menyulitkan pembacaan karena urutannya mudah tertukar. Pecah menjadi tipe bernama atau sederhanakan metodenya agar setiap nilai bermakna.
  • Memakai out dan tuple bersamaan tanpa alasan. Metode yang sudah mengembalikan tuple tidak perlu parameter out tambahan untuk satu nilai lagi, karena elemen baru pada tuple menyelesaikannya dengan lebih ringkas. Pertimbangkan keterbacaan sebelum menambah keduanya sekaligus.

Ringkasan#

  • Tuple dari C# 7 berupa struct ValueTuple yang menampung beberapa nilai dalam satu wadah ringan, dan elemennya boleh diberi nama.
  • Dekonstruksi var (a, b) membongkar tuple atau tipe lain ke variabel terpisah, dan _ menandai nilai yang sengaja tidak dibaca.
  • Pernyataan (a, b) = (b, a) menukar dua variabel tanpa variabel bantu karena dekonstruksi dapat menyasar variabel yang sudah ada.
  • Record posisional memperoleh metode Deconstruct otomatis, sedangkan tipe lain dapat memperolehnya melalui metode Deconstruct dengan parameter out.

Referensi#