out, ref, dan in

Penerusan referensi pada parameter dan pola TryParse.

Daftar isi

Pada parameter biasa, nilai argumen disalin ke parameternya, sehingga pengubahan parameter di dalam metode tidak memengaruhi variabel yang dikirim pemanggil. Kata kunci out, ref, dan in mengubah perilaku itu dengan meneruskan referensi (reference) ke variabel aslinya, sehingga metode membaca dan mengubah variabel pemanggil secara langsung. Topik ini membahas ketiga kata kunci tersebut beserta pola TryParse, yaitu pola penguraian teks yang tidak melempar exception (exception) ketika masukannya tidak sah. Setelah topik ini, satu metode dapat mengembalikan lebih dari satu hasil dan penguraian masukan pengguna dapat ditangani dengan aman.

Tiga kata kunci penerusan referensi#

Ketiga kata kunci menandai parameter yang diteruskan dengan referensi ke variabel aslinya, dan perbedaannya terletak pada kewajiban pemanggil serta kewajiban metode. Perbandingannya dirangkum pada tabel berikut.

Kata kunciNilai awal sebelum dipanggilMetode wajib mengisiMetode boleh mengubah
outtidak perlu diinisialisasiwajibboleh
refwajib diinisialisasitidak wajibboleh
inwajib diinisialisasitidak wajibtidak boleh

Kata kunci out dirancang untuk mengeluarkan hasil dari metode, sehingga metode wajib mengisinya sebelum kembali dan pemanggil boleh mengirim variabel yang masih kosong. Kata kunci ref meneruskan variabel dua arah, sehingga pemanggil wajib menginisialisasinya lebih dahulu dan metode bebas membaca atau mengubahnya. Kata kunci in adalah ref yang hanya bisa dibaca, karena kompilator menolak penugasan pada parameter in di dalam metode. Ketiganya ditulis pada deklarasi dan pada pemanggilan, kecuali in yang boleh dihilangkan di tempat pemanggil demi keringkasan.

Kewajiban menulis out dan ref di tempat pemanggil adalah fitur, bukan beban, karena pembaca baris pemanggil langsung melihat bahwa variabelnya dapat berubah. Karena itu, pilih ref hanya bila perubahan dari dalam metode memang menjadi maksudnya, dan pilih in apabila metode hanya membaca nilai tersebut.

Pola TryParse#

Pola TryParse menguraikan teks menjadi angka dengan mengembalikan status keberhasilan sebagai bool, sedangkan hasil penguraiannya dikirim melalui parameter out. Pendekatan ini menghindari exception, yaitu mekanisme pelontaran error saat program berjalan, apabila teks yang diurai ternyata bukan angka sah. Program utuh berikut menerapkan pola itu pada empat teks masukan sekaligus. Salin programnya ke berkas Program.cs, lalu jalankan dengan dotnet run --file Program.cs.

csharp Program.cs
// Parameter out mengembalikan lebih dari satu hasil dari sebuah metode.

string[] masukan = { "42", "17", "tujuh", "100" };

foreach (string teks in masukan)
{
    if (int.TryParse(teks, out int angka))
    {
        Console.WriteLine($"'{teks}' berhasil diurai menjadi {angka}.");
    }
    else
    {
        Console.WriteLine($"'{teks}' bukan bilangan bulat yang sah.");
    }
}

Bagi(47, 5, out int hasil, out int sisa);
Console.WriteLine($"47 dibagi 5 menghasilkan {hasil} sisa {sisa}.");

// Metode ini mengembalikan hasil bagi dan sisa sekaligus melalui parameter out.
static void Bagi(int pembilang, int penyebut, out int hasil, out int sisa)
{
    hasil = pembilang / penyebut;
    sisa = pembilang % penyebut;
}
text Keluaran
'42' berhasil diurai menjadi 42.
'17' berhasil diurai menjadi 17.
'tujuh' bukan bilangan bulat yang sah.
'100' berhasil diurai menjadi 100.
47 dibagi 5 menghasilkan 9 sisa 2.

Metode int.TryParse mengembalikan false tanpa melempar exception apabila teksnya tidak sah, dan variabel angka dideklarasikan langsung di tempat pemanggilan melalui bentuk out int angka. Apabila penguraian gagal, variabel itu diisi 0, sehingga blok else cukup menampilkan pesan tanpa membaca nilainya. Metode Bagi memakai dua parameter out sekaligus untuk mengembalikan hasil bagi dan sisa dalam satu pemanggilan, sesuatu yang tidak mungkin dilakukan satu nilai kembali biasa. Pola yang sama tersedia untuk tipe lain, misalnya long.TryParse dan double.TryParse, sehingga pola ini menjadi kebiasaan baku penguraian masukan pengguna.

Penggunaan ref dan in#

Parameter ref dipakai apabila metode perlu membaca nilai terkini dan mengirim perubahannya kembali, dan contoh klasiknya adalah pertukaran nilai dua variabel, sesuatu yang tidak mungkin dilakukan parameter biasa karena metode hanya menerima salinan nilainya.

csharp Contoh: ref menukar dua nilai
int a = 3;
int b = 8;
Tukar(ref a, ref b);
Console.WriteLine($"a = {a}, b = {b}");

// Parameter ref membawa nilai masuk ke metode dan membawa hasilnya keluar.
static void Tukar(ref int x, ref int y)
{
    int sementara = x;
    x = y;
    y = sementara;
}
text Keluaran
a = 8, b = 3

Metode Tukar membaca x dan y, lalu menulis keduanya dengan nilai yang ditukar, dan perubahan itu langsung terlihat pada variabel a dan b milik pemanggil. Apabila ref diganti parameter biasa, pertukaran hanya terjadi pada salinan di dalam metode dan keluaran program tidak berubah.

Parameter in menyatakan maksud penerusan referensi yang sama dengan ref, tetapi metodenya dilarang menugaskan parameter tersebut, sehingga maksud hanya baca diperiksa langsung oleh kompilator.

csharp Contoh: in untuk nilai yang hanya dibaca
Console.WriteLine(Volume(2, 3, 4));

// Parameter in hanya boleh dibaca di dalam metode.
static int Volume(in int panjang, in int lebar, in int tinggi)
{
    return panjang * lebar * tinggi;
}
text Keluaran
24

Metode Volume hanya mengalikan ketiga parameternya, sehingga in menyatakan kontrak hanya baca tanpa biaya tambahan. Pada pemanggilan, kata kunci in boleh ditulis maupun dihilangkan, sehingga Volume(2, 3, 4) tanpa kata kunci tetap sah. Untuk nilai berukuran kecil seperti int, penerusan referensi lebih berfungsi sebagai penanda maksud, sedangkan keunggulan kecepatannya baru terasa pada nilai berukuran besar yang penyalinannya mahal.

Kesalahan umum#

Kesalahan pada parameter penerusan referensi umumnya berupa kewajiban yang terlewat, dan hampir semuanya terdeteksi saat kompilasi, bukan saat program berjalan.

  • Parameter out yang tidak diisi pada salah satu jalur ditolak dengan error CS0177, karena metode wajib menugaskan parameter out sebelum kembali.
  • Variabel yang belum diinisialisasi diteruskan ke parameter ref ditolak dengan error CS0165, dan perbaikannya adalah memberi nilai awal sebelum pemanggilan.
  • Penugasan pada parameter in ditolak dengan error CS8331, karena parameternya hanya boleh dibaca di dalam metode.
  • Mengganti int.TryParse dengan int.Parse tanpa pemeriksaan membuat teks tidak sah melempar FormatException saat program berjalan, sehingga pola TryParse lebih diutamakan untuk masukan yang isinya belum pasti.

Ringkasan#

  • Parameter out mengeluarkan hasil dari metode, wajib diisi oleh metode, dan boleh dikirim dalam keadaan kosong.
  • Parameter ref meneruskan variabel dua arah, sedangkan in meneruskannya dalam keadaan hanya baca.
  • Pola TryParse mengembalikan status keberhasilan sebagai bool dan hasilnya melalui parameter out, sehingga teks tidak sah tidak memicu exception.

Referensi#