Hibaelhárítási eljárások (Visual Basic)
Ez a lap néhány gyakori problémát sorol fel, amelyek az eljárások használatakor fordulhatnak elő.
Tömbtípus visszaadása függvényeljárásból
Ha egy Function
eljárás tömb adattípust ad vissza, a Function
névvel nem tárolhat értékeket a tömb elemeiben. Ha megkísérli ezt megtenni, a fordító a függvény hívásaként értelmezi azt.Function
Az alábbi példa fordítóhibákat hoz létre:
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
Az utasítás AllOnes(i) = 1
fordítóhibát generál, mert úgy tűnik, hogy helytelen adattípusú argumentummal (tömb helyett Integer
skalárisInteger
) hívAllOnes
. Az utasítás Return AllOnes()
fordítóhibát generál, mert úgy tűnik, hogy argumentum nélkül hív AllOnes
.
Helyes megközelítés: Ha módosítani szeretné a visszaadni kívánt tömb elemeit, definiáljon egy belső tömböt helyi változóként. Az alábbi példa hiba nélkül fordítja le a következőt:
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
Az argumentumot nem módosítja az eljáráshívás
Ha engedélyezni szeretné, hogy egy eljárás módosítson egy programozási elemet, amely a hívó kód egyik argumentumát alapulja, azt hivatkozással kell átadnia. Egy eljárás azonban akkor is hozzáférhet a hivatkozástípus argumentum elemeihez, ha érték szerint adja át.
Mögöttes változó. Ahhoz, hogy az eljárás lecserélhesse magának a mögöttes változóelemnek az értékét, az eljárásnak deklarálnia kell a ByRef paramétert. Emellett a hívó kódnak nem szabad zárójelbe helyeznie az argumentumot, mert az felülbírálná az átadási
ByRef
mechanizmust.Referenciatípus-elemek. Ha byVal paramétert deklarál, az eljárás nem tudja magát a mögöttes változóelemet módosítani. Ha azonban az argumentum hivatkozástípus, az eljárás módosíthatja annak az objektumnak a tagjait, amelyekre mutat, annak ellenére, hogy nem tudja lecserélni a változó értékét. Ha például az argumentum tömbváltozó, az eljárás nem tud új tömböt hozzárendelni hozzá, de módosíthatja egy vagy több elemét. A módosított elemek megjelennek a hívókód mögöttes tömbváltozójában.
Az alábbi példa két eljárást határoz meg, amelyek érték szerint vesznek fel egy tömbváltozót, és azok elemein működnek. Az eljárás increase
egyszerűen hozzáad egy-egy elemet az egyes elemekhez. Az eljárás replace
egy új tömböt rendel a paraméterhez a()
, majd hozzáad egyet az egyes elemekhez. Az újrahozzárendelés azonban nem befolyásolja a hívó kód mögöttes tömbváltozóját, mert a()
deklarált 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
Az alábbi példa a következő hívásokat kezdeményezi a és replace
a feléincrease
:
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)))
Az első MsgBox
hívás a következőt jeleníti meg: "Növekedés után(n): 11, 21, 31, 41". Mivel n
hivatkozástípusról van szó, increase
módosíthatja a tagjait, annak ellenére, hogy át lett adva ByVal
.
A második MsgBox
hívás a következőt jeleníti meg: "Csere(n): 11, 21, 31, 41". Az n
átadott ByVal
replace
változó n
nem módosítható egy új tömb hozzárendelésével. Amikor replace
létrehozza az új tömbpéldányt k
, és hozzárendeli a helyi változóhoz a
, a hívó kód által átadott hivatkozás n
elveszik. Ha növeli a tagokat a
, az csak a helyi tömböt k
érinti.
Helyes megközelítés: Ha magát az alapul szolgáló változóelemet szeretné módosítani, adja át hivatkozással. Az alábbi példa a deklaráció replace
azon módosítását mutatja be, amely lehetővé teszi, hogy az egyik tömböt lecserélje egy másikra a hívókódban:
Public Sub replace(ByRef a() As Long)
Nem lehet túlterhelést definiálni
Ha egy eljárás túlterhelt verzióját szeretné definiálni, ugyanazt a nevet kell használnia, de más aláírást kell használnia. Ha a fordító nem tudja megkülönböztetni a deklarációt az azonos aláírással rendelkező túlterheléstől, hibát okoz.
Az eljárás aláírását az eljárás neve és a paraméterlista határozza meg. Minden túlterhelésnek ugyanazzal a névvel kell rendelkeznie, mint az összes többi túlterhelés, de legalább az aláírás többi összetevőjében el kell térnie az összestől. További információ: Eljárás túlterhelése.
A következő elemek, bár a paraméterlistára vonatkoznak, nem képezik az eljárás aláírásának összetevőit:
- Eljárásmódosító kulcsszavak, például
Public
,Shared
, ésStatic
. - Paraméternevek.
- Paramétermódosító kulcsszavak, például
ByRef
ésOptional
. - A visszatérési érték adattípusa (a konverziós operátor kivételével).
A fenti elemek közül csak egy vagy több módosításával nem lehet túlterhelni az eljárásokat.
Helyes megközelítés: Az eljárás túlterheltségének meghatározásához meg kell változtatnia az aláírást. Mivel ugyanazt a nevet kell használnia, meg kell változtatnia a paraméterek számát, sorrendjét vagy adattípusát. Általános eljárás esetén a típusparaméterek száma változhat. Egy konverziós operátorban (CType függvény) a visszatérési típust módosíthatja.
Túlterhelés feloldása választható és ParamArray argumentumokkal
Ha egy vagy több Választható paraméterrel vagy ParamArray paraméterrel túlterhel egy eljárást, el kell kerülnie az implicit túlterhelések duplikálását. További információ: Szempontok a túlterhelési eljárásokban.
Túlterhelt eljárás helytelen verziójának meghívása
Ha egy eljárás több túlterhelt verzióval is rendelkezik, ismernie kell az összes paraméterlistát, és tisztában kell lennie azzal, hogy a Visual Basic hogyan oldja fel a túlterhelések közötti hívásokat. Ellenkező esetben a kívánttól eltérő túlterhelést is hívhat.
Ha megállapította, hogy melyik túlterhelést szeretné meghívni, ügyeljen az alábbi szabályok betartására:
- Adja meg a megfelelő számú argumentumot, és a megfelelő sorrendben.
- Ideális esetben az argumentumoknak pontosan ugyanazokkal az adattípusokkal kell rendelkezniük, mint a megfelelő paramétereknek. Az egyes argumentumok adattípusának minden esetben ki kell szélesítenie a megfelelő paraméter adattípusát. Ez akkor is igaz, ha az Option Strict Utasítás értéke
Off
. Ha egy túlterheltség az argumentumlistából való leszűkítést igényel, a túlterhelés nem hívható meg. - Ha olyan argumentumokat ad meg, amelyek szélesítést igényelnek, az adattípusokat a lehető legközelebb kell hoznia a megfelelő paraméteradattípusokhoz. Ha két vagy több túlterhelés fogadja el az argumentum adattípusait, a fordító feloldja a hívást arra a túlterhelésre, amely a legkisebb mértékű szélesítést kéri.
Az argumentumok előkészítésekor csökkentheti az adattípusok eltérésének esélyét a CType függvény konvertálási kulcsszójának használatával.
Túlterhelésfeloldási hiba
Ha túlterhelt eljárást hív meg, a fordító megpróbálja kiküszöbölni az összes túlterhelést. Ha sikerül, feloldja a túlterhelésre irányuló hívást. Ha kiküszöböli az összes túlterhelést, vagy nem tudja egyetlen jelöltre csökkenteni a jogosult túlterheléseket, hibát okoz.
Az alábbi példa a túlterhelésfeloldási folyamatot szemlélteti:
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)
Az első hívásban a fordító megszünteti az első túlterhelést, mivel az első argumentum típusa (Short
) a megfelelő paraméterByte
típusára () szűkül. Ezzel kiküszöböli a harmadik túlterhelést, mivel a második túlterhelés (Short
és ) argumentumtípusai a harmadik túlterhelés (Integer
és Single
Single
) megfelelő típusára szélesednek. A második túlterhelés kisebb szélesítést igényel, ezért a fordító ezt használja a híváshoz.
A második hívásban a fordító nem tudja megszüntetni a túlterheléseket a szűkítés alapján. Kiküszöböli a harmadik túlterhelést ugyanazért, mint az első hívásban, mert meghívhatja a második túlterhelést az argumentumtípusok kevésbé szélesítésével. A fordító azonban nem tud feloldani az első és a második túlterhelés között. Mindegyik egy definiált paramétertípussal rendelkezik, amely a másikban a megfelelő típusra (Byte
a értékre, de Single
a értékreShort
) szélesedik.Double
A fordító ezért túlterhelésfeloldási hibát okoz.
Helyes megközelítés: Ha kétértelműség nélkül szeretne meghívni egy túlterhelt eljárást, használja a CType függvényt az argumentum adattípusainak és a paramétertípusoknak való egyeztetéséhez. Az alábbi példában egy hívás z
látható, amely a második túlterhelésre kényszeríti a feloldásokat.
Call z(CType(p, Short), CType(q, Single))
Túlterhelés feloldása választható és ParamArray argumentumokkal
Ha egy eljárás két túlterhelése azonos aláírással rendelkezik, azzal a kivételével, hogy az utolsó paraméter nem kötelező az egyikben, a másikban a ParamArray , a fordító a legközelebbi egyezésnek megfelelően oldja fel az eljárás hívását. További információ: Túlterhelés feloldás.