Prosedur pemecahan masalah (Visual Basic)

Halaman ini mencantumkan beberapa masalah umum yang dapat terjadi saat bekerja dengan prosedur.

Mengembalikan jenis array dari prosedur fungsi

Jika prosedur Function mengembalikan jenis data array, Anda tidak dapat menggunakan nama Function untuk menyimpan nilai dalam elemen array. Jika Anda mencoba melakukan ini, compiler menafsirkannya sebagai panggilan ke Function. Contoh berikut menghasilkan compiler error:

Function AllOnes(n As Integer) As Integer()
   For i As Integer = 1 To n - 1  
      ' The following statement generates a COMPILER ERROR.  
      AllOnes(i) = 1  
   Next  

   ' The following statement generates a COMPILER ERROR.  
   Return AllOnes()  
End Function

Pernyataan AllOnes(i) = 1 menghasilkan compiler error karena tampaknya memanggil AllOnes dengan argumen jenis data yang salah (skalar Integer alih-alih array Integer). Pernyataan Return AllOnes() menghasilkan compiler error karena tampaknya memanggil AllOnes tanpa argumen.

Pendekatan yang benar: Agar dapat memodifikasi elemen array yang akan dikembalikan, tentukan array internal sebagai variabel lokal. Contoh berikut mengompilasi tanpa kesalahan:

Function AllOnes(n As Integer) As Integer()
    Dim iArray(n - 1) As Integer
    For i = 0 To n - 1
        iArray(i) = 1
    Next
    Return iArray
End Function

Argumen tidak dimodifikasi oleh panggilan prosedur

Jika Anda berniat mengizinkan prosedur untuk mengubah elemen pemrograman yang mendasar argumen dalam kode panggilan, Anda harus meneruskannya dengan referensi. Tetapi prosedur dapat mengakses elemen argumen jenis referensi meskipun Anda meneruskannya berdasarkan nilai.

  • Variabel yang mendasar. Untuk memungkinkan prosedur mengganti nilai elemen variabel yang mendasar itu sendiri, prosedur harus mendeklarasikan parameter ByRef. Selain itu, kode panggilan tidak boleh mengapit argumen dalam tanda kurung, karena itu akan mengambil alih mekanisme ByRef passing.

  • Elemen jenis referensi. Jika Anda mendeklarasikan parameter ByVal, prosedur tidak dapat mengubah elemen variabel yang mendasar itu sendiri. Namun, jika argumen adalah jenis referensi, prosedur dapat memodifikasi anggota objek yang ditujukannya, meskipun tidak dapat menggantikan nilai variabel. Misalnya, jika argumen adalah variabel array, prosedur tidak dapat menetapkan array baru ke dalamnya, tetapi dapat mengubah satu atau beberapa elemennya. Elemen yang diubah tercermin dalam variabel array yang mendasar dalam kode panggilan.

Contoh berikut menentukan dua prosedur yang mengambil variabel array berdasarkan nilai dan beroperasi pada elemennya. Prosedur increase hanya menambah satu ke setiap elemen. Prosedur replace menetapkan array baru ke parameter a() lalu menambahkannya ke setiap elemen. Namun, penetapan ulang tidak memengaruhi variabel array yang mendasar dalam kode panggilan karena a() dinyatakan ByVal.

Public Sub increase(ByVal a() As Long)
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub
Public Sub replace(ByVal a() As Long)
    Dim k() As Long = {100, 200, 300}
    a = k
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub

Contoh berikut melakukan panggilan ke increase dan replace:

Dim n() As Long = {10, 20, 30, 40}
Call increase(n)
MsgBox("After increase(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
Call replace(n)
MsgBox("After replace(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))

Panggilan pertama MsgBox menampilkan "Setelah peningkatan(n): 11, 21, 31, 41". Karena n merupakan jenis referensi, increase dapat mengubah anggotanya, meskipun diteruskan ByVal.

Panggilan MsgBox kedua menampilkan "Setelah mengganti(n): 11, 21, 31, 41". Karena n diteruskan ByVal, replace tidak dapat mengubah variabel n dengan menetapkan array baru ke dalamnya. Saat replace membuat instans array baru k dan menetapkannya ke variabel lokal a, ini kehilangan referensi ke n yang diteruskan oleh kode panggilan. Saat menaikkan anggota a, hanya array lokal k yang terpengaruh.

Pendekatan yang benar: Untuk dapat memodifikasi elemen variabel yang mendasar itu sendiri, teruskan dengan referensi. Contoh berikut menunjukkan perubahan dalam deklarasi replace yang memungkinkannya mengganti satu array dengan array lainnya dalam kode panggilan:

Public Sub replace(ByRef a() As Long)

Tidak dapat menentukan overload

Jika Anda ingin menentukan versi prosedur yang overload, Anda harus menggunakan nama yang sama tetapi tanda tangan yang berbeda. Jika compiler tidak dapat membedakan deklarasi Anda dari overload dengan tanda tangan yang sama, itu menghasilkan kesalahan.

Tanda tangan dari suatu prosedur ditentukan oleh nama prosedur dan daftar parameter. Setiap overload harus memiliki nama yang sama dengan semua overload lainnya tetapi harus berbeda dari semuanya di setidaknya salah satu komponen lain dari tanda tangan. Untuk informasi selengkapnya, lihat Overloading Prosedur.

Item berikut, meskipun berkaitan dengan daftar parameter, bukan komponen tanda tangan prosedur:

  • Kata kunci pengubah prosedur, seperti Public, Shared, dan Static.
  • Nama parameter.
  • Kata kunci modifikasi parameter, seperti ByRef dan Optional.
  • Jenis data dari nilai pengembalian (kecuali untuk operator konversi).

Secara khusus, Anda tidak dapat membebani prosedur dengan memvariasikan hanya satu atau lebih dari item sebelumnya.

Pendekatan yang benar: Agar dapat menentukan overload prosedur, Anda harus memvariasikan tanda tangan. Karena Anda harus menggunakan nama yang sama, Anda harus memvariasikan jumlah, urutan, atau jenis data parameter. Dalam prosedur generik, Anda dapat memvariasikan jumlah parameter jenis. Di operator konversi (Fungsi CType), Anda dapat memvariasikan jenis pengembalian.

Resolusi overload dengan argumen Opsional dan ParamArray

Jika Anda membebani prosedur dengan satu atau beberapa parameter Opsional atau parameter ParamArray, Anda harus menghindari duplikat overload implisit. Untuk informasi, lihat Pertimbangan dalam Prosedur overload.

Memanggil versi prosedur yang overload yang salah

Jika prosedur memiliki beberapa versi yang overload, Anda harus terbiasa dengan semua daftar parameternya dan memahami bagaimana Visual Basic menyelesaikan panggilan di antara overload. Jika tidak, Anda dapat memanggil overload selain yang dimaksudkan.

Saat Anda telah menentukan overload mana yang ingin Anda panggil, berhati-hatilah untuk mengamati aturan berikut:

  • Berikan jumlah argumen yang benar, dan dalam urutan yang benar.
  • Idealnya, argumen Anda harus memiliki jenis data yang sama persis dengan parameter yang sesuai. Bagaimanapun, jenis data dari setiap argumen harus melebar ke parameter yang sesuai. Ini benar bahkan dengan Pernyataan Ketat Opsi diatur ke Off. Jika overload memerlukan konversi yang menyempit dari daftar argumen Anda, overload tersebut tidak memenuhi syarat untuk dipanggil.
  • Jika Anda menyediakan argumen yang memerlukan pelebaran, buat jenis datanya sedekat mungkin dengan jenis data parameter yang sesuai. Jika dua atau lebih overload menerima jenis data argumen Anda, compiler menyelesaikan panggilan Anda ke overload yang memanggil untuk jumlah pelebaran paling sedikit.

Anda dapat mengurangi kemungkinan ketidakcocokan jenis data dengan menggunakan kata kunci konversi Fungsi CType saat menyiapkan argumen Anda.

Kegagalan resolusi overload

Saat Anda memanggil prosedur yang overload, compiler mencoba untuk menghilangkan semua kecuali salah satu overload. Jika berhasil, itu menyelesaikan panggilan ke overload tersebut. Jika menghilangkan semua overload, atau jika tidak dapat mengurangi overload yang memenuhi syarat menjadi satu kandidat, itu menghasilkan kesalahan.

Contoh berikut mengilustrasikan proses resolusi overload:

Overloads Sub z(ByVal x As Byte, ByVal y As Double)
End Sub
Overloads Sub z(ByVal x As Short, ByVal y As Single)
End Sub
Overloads Sub z(ByVal x As Integer, ByVal y As Single)
End Sub
Dim r, s As Short
Call z(r, s)
Dim p As Byte, q As Short
' The following statement causes an overload resolution error.
Call z(p, q)

Dalam panggilan pertama, compiler menghilangkan overload pertama karena jenis argumen pertama (Short) menyempit ke jenis parameter yang sesuai (Byte). Kemudian menghilangkan overload ketiga karena setiap jenis argumen dalam overload kedua (Short dan Single) melebar ke jenis yang sesuai dalam overload ketiga (Integer dan Single). Overload kedua membutuhkan lebih sedikit pelebaran, sehingga compiler menggunakannya untuk panggilan.

Dalam panggilan kedua, compiler tidak dapat menghilangkan salah satu overload berdasarkan penyempitan. Ini menghilangkan overload ketiga karena alasan yang sama seperti pada panggilan pertama, karena dapat memanggil overload kedua dengan lebih sedikit pelebaran jenis argumen. Namun, compiler tidak dapat menyelesaikan antara overload pertama dan kedua. Masing-masing memiliki satu jenis parameter yang ditentukan yang melebar ke jenis yang sesuai di yang lain (Byte ke Short, tetapi Single ke Double). Oleh karena itu, compiler menghasilkan kesalahan resolusi overload.

Pendekatan yang benar: Agar dapat memanggil prosedur overload tanpa ambiguitas, gunakan Fungsi CType untuk mencocokkan jenis data argumen dengan jenis parameter. Contoh berikut menunjukkan panggilan ke z yang memaksa resolusi ke overload kedua.

Call z(CType(p, Short), CType(q, Single))

Resolusi overload dengan argumen Opsional dan ParamArray

Jika dua overload prosedur memiliki tanda tangan yang identik kecuali bahwa parameter terakhir dinyatakan Opsional dalam satu dan ParamArray di yang lain, compiler menyelesaikan panggilan ke prosedur tersebut sesuai dengan kecocokan terdekat. Untuk informasi selengkapnya, lihat Resolusi Overload.

Lihat juga