Hanya karena Anda bisa melakukan sesuatu, bukan berarti Anda harus melakukannya.
Saya sangat percaya pada kesucian kompatibilitas ke belakang. Tapi itu datang dengan sisi gelap. Terkadang cara lama dalam melakukan sesuatu tidak lagi disukai. Penggunaannya menjadi sangat misterius sehingga kita cenderung melupakan keberadaan mereka.
Begitu juga dengan pernyataan DefType.
Apa yang Tidak Anda Ketahui Dapat Menyakiti Anda
Beberapa bulan yang lalu, saya menulis artikel tentang modul kelas Operasi Registri Romke Soldaat.
Saya memublikasikan perubahan yang saya buat pada deklarasi API Romke untuk membuat kode berjalan di bawah VBA 64-bit. Setiap panggilan API dibungkus dengan #If VBA7
tag kompilasi bersyarat dan diperbarui dengan PtrSafe
kata kunci.
Hanya ada satu masalah.
Saya lupa menyertakan perubahan kunci yang telah saya buat pada salah satu deklarasi tingkat modul dalam kode Romke. Tanpa perubahan ini, kode modifikasi Romke tidak akan dikompilasi di bawah VBA 64-bit. Kesalahan kompilasi terjadi pada baris berikut:
Pesan kesalahannya adalah "Ketidakcocokan tipe argumen ByRef " dan variabel yang disorot adalah hCurKey
.
Berikut baris kode yang menyinggung dari modul kelas asli Romke:
Private hCurKey
Untuk memperbaiki kesalahan kompilasi, baris kode di atas dapat diubah menjadi ini:
Private hCurKey As Variant
Tapi tunggu, katamu, bukankah kedua baris kode itu melakukan hal yang sama?!?! Semua orang tahu bahwa jika Anda tidak mendeklarasikan tipe variabel di VBA, itu secara implisit dideklarasikan sebagai Varian. ... Atau ya?
Eksplisit Lebih Baik Daripada Implisit
Jadi apa yang sebenarnya terjadi di sini?
Masalahnya adalah baris pertama kode di atas–Private hCurKey
–mendefinisikan variabel hCurKey sebagai Long
tipe data.
Bagaimana ini bisa terjadi?
Itu karena baris aneh ini di bagian atas modul kelas Romke:
DefLng H-I, L, N
Apa yang dilakukan garis itu? Dikatakan bahwa setiap variabel yang dideklarasikan dalam modul saat ini tanpa tipe yang dideklarasikan secara eksplisit yang nama variabelnya dimulai dengan H
, I
, L
, atau N
, akan diperlakukan oleh kompiler sebagai Long
tipe data.
Jadi, baris Private hCurKey
melakukan secara implisit mendeklarasikan tipe untuk variabel hCurKey, tetapi deklarasi implisit adalah sebagai tipe data Long, bukan Varian.
Mengapa Bervariasi Kompilasi Tapi Panjang Bukan?
Mengapa kode dikompilasi saat hCurKey
adalah Varian tetapi gagal saat Long, itu masalah proses konversi 32-bit ke 64-bit.
Untuk menemukan sumber masalahnya, kita perlu memeriksa kode yang dimigrasikan untuk deklarasi API RegCreateKeyEx:
#If VBA7 Then
Private Declare PtrSafe Function RegCreateKeyEx _
Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
ByVal hKey As LongPtr, ByVal lpSubKey As String, _
ByVal Reserved As Long, ByVal lpClass As String, _
ByVal dwOptions As Long, ByVal samDesired As Long, _
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
phkResult As LongPtr, lpdwDisposition As Long) As Long
#Else
Private Declare Function RegCreateKeyEx _
Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
ByVal hKey As Long, ByVal lpSubKey As String, _
ByVal Reserved As Long, ByVal lpClass As String, _
ByVal dwOptions As Long, ByVal samDesired As Long, _
lpSecurityAttributes As SECURITY_ATTRIBUTES, _
phkResult As Long, lpdwDisposition As Long) As Long
#End If
Saat kita memanggil RegCreateKeyEx
dari kode, kami melewati hCurKey
variabel sebagai argumen kedua hingga terakhir dalam fungsi. Dengan kata lain, itu diteruskan sebagai phkResult
argumen. Perhatikan bahwa dalam versi pra-VBA7 (Access 2007 dan sebelumnya), phkResult
dideklarasikan sebagai Long, tetapi dalam versi VBA7 dideklarasikan sebagai LongPtr
.
Itu karena phkResult
menerima pegangan ke kunci registri yang dibuat atau dibuka. Setiap kali Anda melihat kata "pegangan" yang terkait dengan panggilan API, Anda dapat menerjemahkannya dengan aman di kepala Anda ke "alamat memori". Itu sebabnya argumen didefinisikan ulang sebagai LongPtr
dalam kode VBA7:saat mengeksekusi di lingkungan 32-bit, sebuah LongPtr
diperlakukan sebagai Long
32-bit integer, tetapi dalam lingkungan 64-bit, sebuah LongPtr
diperlakukan sebagai LongLong
64-bit bilangan bulat.
Mendeklarasikan hCurKey
sebagai Variant adalah sedikit jalan pintas. Adaptasi berikut juga akan berfungsi (dan bekerja lebih cepat, meskipun peningkatan kecepatan mungkin tidak terlihat oleh pengguna kecuali jika dipanggil berkali-kali di dalam satu lingkaran):
#If VBA7 Then
Private hCurKey As LongPtr
#Else
Private hCurKey As Long
#End If
Seperti yang saya katakan, pendekatan di atas lebih eksplisit dalam menyampaikan maksud pengembang, berkinerja lebih baik, dan akan meningkatkan lebih banyak kesalahan waktu kompilasi daripada Private hCurKey As Variant
alternatif.
Tapi saya dikenal pemalas, dan Private hCurKey As Variant
adalah hampir sama baiknya dengan lebih sedikit mengetik.
Gunakan Pengetahuan Anda Untuk Kebaikan
Sekarang, ingat apa yang saya katakan di awal artikel ini?
Hanya karena Anda bisa melakukan sesuatu, bukan berarti Anda harus melakukannya.
Saya menulis artikel ini karena dua alasan:
- Untuk mendorong Anda untuk secara eksplisit mendeklarasikan Variabel Variant
As Variant
- Untuk meningkatkan kesadaran tentang aspek misterius VBA yang dapat membuat Anda tersandung jika Anda mempertahankan (atau menyalin-menempel) kode orang lain
Saya TIDAK tulis artikel ini untuk menginspirasi Anda untuk menulis pernyataan DefType dalam kode Anda sendiri. JANGAN LAKUKAN ITU!!! Ingat, hanya karena Anda bisa melakukan sesuatu bukan berarti Anda harus melakukannya.