Parameter adalah nama yang dideklarasikan pada kepala prosedur untuk menampung data yang dikirim pemanggil, sedangkan argumen adalah nilai nyata yang dikirim saat pemanggilan. VB.NET menyediakan dua mekanisme pengiriman, yaitu ByVal yang mengirim salinan nilai dan ByRef yang mengirim referensi ke variabel pemanggil. Topik ini membahas perbedaan kedua mekanisme pada tipe nilai dan tipe referensi, penggunaan parameter Optional dengan nilai bawaan, serta pemanggilan dengan argumen bernama. Pemahaman ini penting karena mekanisme pengiriman menentukan apakah prosedur dapat mengubah data milik pemanggil.
Mekanisme pengiriman ByVal dan ByRef#
ByVal menyalin isi argumen ke parameter, sehingga perubahan pada parameter tidak pernah terlihat oleh pemanggil. ByRef mengirim alamat variabel pemanggil, sehingga parameter dan variabel pemanggil menunjuk tempat penyimpanan yang sama dan setiap perubahan langsung terlihat. Pilihan kata kunci dituliskan pada deklarasi parameter, misalnya Sub NaikkanByVal(ByVal n As Integer) atau Sub NaikkanByRef(ByRef n As Integer).
Perbedaan keduanya dirangkum pada tabel berikut.
| Aspek | ByVal | ByRef |
|---|---|---|
| Yang dikirim ke prosedur | salinan isi argumen | referensi ke variabel pemanggil |
| Perubahan parameter pada tipe nilai | tidak terlihat pemanggil | terlihat pemanggil |
| Penggantian objek pada tipe referensi | tidak terlihat pemanggil | terlihat pemanggil |
| Argumen berupa literal atau konstanta | diterima | diterima, tetapi perubahannya hilang |
Butir terakhir pada tabel menunjukkan perlindungan alami ByVal. Pemanggil menjadi aman dari perubahan yang tidak disengaja, dan itulah alasan ByVal dijadikan mekanisme bawaan.
Membuktikan perbedaan dengan program#
Program berikut membandingkan kedua mekanisme pada variabel tunggal sekaligus pada array. Jalankan berkasnya dengan dotnet run, lalu perhatikan dua kelompok keluarannya, yaitu yang berkaitan dengan skor dan yang berkaitan dengan array data.
Module Program
Sub NaikkanByVal(ByVal n As Integer)
n += 1
Console.WriteLine($" di dalam prosedur (ByVal): {n}")
End Sub
Sub NaikkanByRef(ByRef n As Integer)
n += 1
Console.WriteLine($" di dalam prosedur (ByRef): {n}")
End Sub
Sub GantiElemenPertama(ByVal angka() As Integer)
angka(0) = 99
End Sub
Sub TimpaArray(ByVal angka() As Integer)
angka = New Integer() {7, 7}
End Sub
Sub GantiSeluruhArray(ByRef angka() As Integer)
angka = New Integer() {5, 5}
End Sub
Sub Main()
Dim skor As Integer = 10
Console.WriteLine($"Sebelum ByVal: {skor}")
NaikkanByVal(skor)
Console.WriteLine($"Sesudah ByVal: {skor}")
Console.WriteLine($"Sebelum ByRef: {skor}")
NaikkanByRef(skor)
Console.WriteLine($"Sesudah ByRef: {skor}")
Dim data() As Integer = {1, 2}
GantiElemenPertama(data)
Console.WriteLine($"Sesudah ByVal mengubah isi: {data(0)}")
TimpaArray(data)
Console.WriteLine($"Sesudah ByVal mengganti objek: {data(0)}")
GantiSeluruhArray(data)
Console.WriteLine($"Sesudah ByRef mengganti objek: {data(0)}")
End Sub
End ModuleSebelum ByVal: 10
di dalam prosedur (ByVal): 11
Sesudah ByVal: 10
Sebelum ByRef: 10
di dalam prosedur (ByRef): 11
Sesudah ByRef: 11
Sesudah ByVal mengubah isi: 99
Sesudah ByVal mengganti objek: 99
Sesudah ByRef mengganti objek: 5Tiga baris pertama memperlihatkan skor tetap bernilai 10 setelah NaikkanByVal dijalankan, sedangkan tiga baris berikutnya memperlihatkan skor menjadi 11 setelah NaikkanByRef dijalankan. Diagram berikut menggambarkan sebabnya, yaitu ByVal bekerja pada salinan dan ByRef bekerja pada variabel asli.
Keenam prosedur pada berkas itu sengaja dibuat pendek agar pasangannya mudah dibandingkan. NaikkanByVal dan NaikkanByRef berbeda hanya pada kata kunci parameternya, sehingga seluruh perbedaan keluaran pasti bersumber dari mekanisme pengirimannya. Tiga prosedur array berikutnya memeriksa kasus yang lebih halus, yaitu apa yang berubah dan apa yang tidak ketika tipe referensi dikirim dengan dua mekanisme berbeda.
Tipe nilai dan tipe referensi#
Perilaku array pada keluaran di atas menunjukkan interaksi antara mekanisme pengiriman dan jenis tipe data. Tipe nilai (value type) seperti Integer dan Double menyimpan datanya sendiri, sedangkan tipe referensi (reference type) seperti array menyimpan alamat menuju datanya. Variabel data tidak memuat dua angka itu, melainkan alamat menuju keduanya.
Pada GantiElemenPertama, parameter angka dideklarasikan ByVal, tetapi yang disalin hanyalah alamatnya, sehingga alamat aslinya tetap menunjuk array milik pemanggil. Pengisian angka(0) = 99 mengubah isi objek yang sama, dan keluarannya memperlihatkan elemen pertama berubah menjadi 99. Sebaliknya, TimpaArray mengganti parameter dengan array baru berisi 7 dan 7, dan peristiwa itu hanya terjadi pada variabel lokalnya, sehingga data milik pemanggil tidak tersentuh. Hanya GantiSeluruhArray dengan ByRef yang dapat mengarahkan variabel pemanggil ke objek baru, dan keluarannya memperlihatkan elemen pertama menjadi 5.
Kesimpulannya, ByVal pada tipe referensi tetap mengizinkan prosedur mengubah isi objek, tetapi melarangnya mengganti objek milik pemanggil. Aturan praktisnya, gunakan ByVal sebagai pilihan awal dan pindah ke ByRef hanya ketika prosedur memang harus mengembalikan hasil melalui parameternya.
Parameter Optional dengan nilai bawaan#
Parameter Optional adalah parameter yang boleh tidak dikirim pemanggil, dan saat itu terjadi, compiler mengisinya dengan nilai bawaan (default) yang ditetapkan pada deklarasi. Nilai bawaan harus berupa ekspresi konstan, misalnya angka tetap atau teks tetap. Parameter wajib selalu dituliskan lebih dahulu, sehingga parameter Optional menempati akhir daftar parameter.
Program tiket loket berikut menggunakan Optional untuk biaya layanan dan asuransi. Tarif dasar wajib dikirim, sedangkan dua parameter sisanya boleh dikosongkan dan otomatis diisi nilainya masing-masing.
Module Program
Function HargaTiket(tarifDasar As Integer, Optional biayaLayanan As Integer = 5, Optional asuransi As Integer = 0) As Integer
Return tarifDasar + biayaLayanan + asuransi
End Function
Sub Main()
Console.WriteLine($"Tiket dasar : {HargaTiket(20)}")
Console.WriteLine($"Layanan naik : {HargaTiket(20, 8)}")
Console.WriteLine($"Semua diisi : {HargaTiket(20, 8, 3)}")
Console.WriteLine($"Asuransi saja : {HargaTiket(20, asuransi:=4)}")
Console.WriteLine($"Urutan ditukar : {HargaTiket(asuransi:=4, tarifDasar:=30)}")
End Sub
End ModuleTiket dasar : 25
Layanan naik : 28
Semua diisi : 31
Asuransi saja : 29
Urutan ditukar : 39Baris Tiket dasar mengirim satu argumen saja, sehingga biayaLayanan terisi 5, asuransi terisi 0, dan jumlahnya 25. Baris Asuransi saja memperlihatkan pemanggilan dengan argumen bernama asuransi:=4, yaitu cara menuliskan nama:=nilai yang memungkinkan satu parameter tengah dilompati tanpa menulis ulang nilai bawaannya. Baris terakhir menunjukkan argumen bernama juga boleh ditukar urutannya, dan hasilnya tetap dihitung dengan benar.
Kesalahan umum#
Kesalahan pertama adalah mengira ByVal pada tipe referensi melindungi isi objek. Contohnya sudah terlihat pada GantiElemenPertama, yaitu isi array tetap berubah meskipun parameternya ByVal. Bila prosedur tidak boleh mengubah isi objek sama sekali, kirim salinannya atau rancang parameternya sebagai tipe yang tidak dapat diubah.
Kesalahan kedua adalah mengirim literal atau ekspresi ke parameter ByRef. VB.NET menerimanya dengan membuat salinan sementara, sehingga program tetap berjalan, tetapi perubahan pada parameter itu tidak pernah sampai ke pemanggil. NaikkanByRef(10) menaikkan salinan sementara menjadi 11 dan setelah itu nilainya hilang. Kirimkan variabel, bukan literal angka, apabila hasil prosedur memang ingin diambil dari parameternya, dan ujilah dengan mencetak variabel pemanggil sesudah pemanggilan agar perubahan yang hilang terlihat sejak awal.
Kesalahan ketiga adalah menumpuk parameter Optional untuk kebutuhan yang perilakunya berbeda-beda. Sebuah prosedur dengan lima parameter Optional sulit dibaca dan mudah dipanggil dengan keliru. Apabila variasinya mengubah cara kerja prosedur, jalur yang lebih tepat adalah overloading, yaitu menyediakan beberapa tanda tangan untuk satu nama prosedur.
Ringkasan#
ByValmengirim salinan nilai sehingga pemanggil terlindungi dari perubahan, sedangkanByRefmengirim referensi sehingga perubahan parameter terlihat pemanggil.- Pada tipe referensi yang dikirim
ByVal, isi objek masih dapat diubah, tetapi penggantian objek hanya efektif bila parameternyaByRef. - Parameter
Optionalditempatkan di akhir daftar parameter, diisi nilai bawaan konstan, dan dapat dilompati dengan menuliskan argumen bernama berbentuknama:=nilai.
Referensi#
- Passing Arguments by Value and by Reference — Microsoft Learn — Penjelasan mekanisme pengiriman dan interaksinya dengan jenis tipe data.
- ByVal — Microsoft Learn
— Dokumentasi kata kunci
ByValbeserta catatan bahwa ia adalah mekanisme bawaan. - Optional Parameters — Microsoft Learn
— Aturan parameter
Optionaldan pemanggilan dengan argumen bernama. - Passing Arguments by Position and by Name — Microsoft Learn — Sintaks argumen bernama dan manfaatnya.