Postupy řešení potíží (Visual Basic)
Tato stránka obsahuje některé běžné problémy, ke kterým může dojít při práci s postupy.
Vrácení typu pole z procedury funkce
Pokud procedura Function
vrátí datový typ pole, nelze název použít Function
k uložení hodnot v prvek pole. Pokud se o to pokusíte, kompilátor ji interpretuje jako volání Function
. Následující příklad generuje chyby kompilátoru:
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
Příkaz AllOnes(i) = 1
generuje chybu kompilátoru, protože se zdá, že volá AllOnes
s argumentem nesprávného datového typu (skalární Integer
místo Integer
pole). Příkaz Return AllOnes()
generuje chybu kompilátoru, protože se zdá, že volá AllOnes
bez argumentu.
Správný přístup: Chcete-li upravit prvky pole, které má být vráceno, definujte interní pole jako místní proměnnou. Následující příklad se zkompiluje bez chyby:
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
Argument nebyl změněn voláním procedury
Pokud máte v úmyslu povolit proceduru změnit prvek programování, který je podkladem argumentu ve volajícím kódu, musíte jej předat odkazem. Procedura ale může přistupovat k prvkům argumentu typu odkazu, i když ho předáte podle hodnoty.
Podkladová proměnná. Aby procedura mohla nahradit hodnotu samotného elementu podkladové proměnné, musí procedura deklarovat parametr ByRef. Volající kód také nesmí argument uzavřít do závorek, protože by to přepsal
ByRef
mechanismus předávání.Prvky typu odkazu. Pokud deklarujete parametr ByVal, procedura nemůže upravit samotný element podkladové proměnné. Pokud je však argument odkazovým typem, může procedura změnit členy objektu, na který odkazuje, i když nemůže nahradit hodnotu proměnné. Pokud je argumentem například proměnná pole, nemůže mu procedura přiřadit nové pole, ale může změnit jeden nebo více jeho prvků. Změněné prvky se projeví v podkladové proměnné pole ve volajícím kódu.
Následující příklad definuje dva postupy, které přebírají proměnnou pole podle hodnoty a pracují s jejími prvky. Procedura increase
jednoduše přidá ke každému prvku jeden prvek. Procedura replace
přiřadí nové pole k parametru a()
a pak přidá jedno do každého prvku. Změna přiřazení však nemá vliv na podkladovou proměnnou pole ve volajícím kódu, protože a()
je deklarován 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
Následující příklad volá increase
a 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)))
Při prvním MsgBox
volání se zobrazí zpráva "After increase(n): 11, 21, 31, 41" (Po zvýšení(n): 11, 21, 31, 41. Vzhledem k tomu n
, že je typ odkazu, increase
může změnit své členy, i když je předán ByVal
.
Při druhém MsgBox
volání se zobrazí "After replace(n): 11, 21, 31, 41". Protože n
je předaný ByVal
, replace
nemůže proměnnou n
změnit přiřazením nového pole. Když replace
vytvoří novou instanci k
pole a přiřadí ji k místní proměnné a
, ztratí odkaz na n
předaný volajícím kódem. Když zvýší počet členů a
nástroje , ovlivní se pouze místní pole k
.
Správný přístup: Pokud chcete upravit samotný element podkladové proměnné, předejte ho odkazem. Následující příklad ukazuje změnu v deklaraci replace
, která umožňuje nahradit jedno pole jiným ve volajícím kódu:
Public Sub replace(ByRef a() As Long)
Nelze definovat přetížení
Pokud chcete definovat přetíženou verzi procedury, musíte použít stejný název, ale jiný podpis. Pokud kompilátor nedokáže odlišit deklaraci od přetížení se stejným podpisem, vygeneruje chybu.
Podpis procedury je určen názvem procedury a seznamem parametrů. Každé přetížení musí mít stejný název jako všechna ostatní přetížení, ale musí se od všech lišit alespoň v jedné z ostatních součástí podpisu. Další informace najdete v tématu Přetížení procedury.
Následující položky, i když se týkají seznamu parametrů, nejsou součástí podpisu procedury:
- Klíčová slova modifikátoru procedury, například
Public
,Shared
aStatic
. - Názvy parametrů.
- Klíčová slova modifikátoru parametrů, například
ByRef
aOptional
. - Datový typ návratové hodnoty (s výjimkou operátoru převodu).
Proceduru nelze přetěžovat tak, že bude měnit pouze jednu nebo více předchozích položek.
Správný přístup: Chcete-li definovat přetížení procedury, je nutné měnit podpis. Vzhledem k tomu, že musíte použít stejný název, musíte u parametrů měnit počet, pořadí nebo datové typy. V obecné proceduře můžete počet parametrů typu měnit. V operátoru převodu (funkce CType) můžete měnit návratový typ.
Rozlišení přetížení s volitelnými argumenty a argumenty ParamArray
Pokud přetěžujete proceduru s jedním nebo více volitelnými parametry nebo parametrem ParamArray , musíte se vyhnout duplikování jakéhokoli implicitního přetížení. Informace najdete v části Důležité informace v postupech přetížení.
Volání nesprávné verze přetížené procedury
Pokud má procedura několik přetížených verzí, měli byste být obeznámeni se všemi jejich seznamy parametrů a pochopit, jak Visual Basic řeší volání mezi přetíženími. Jinak byste mohli volat jiné než zamýšlené přetížení.
Po určení přetížení, které chcete volat, buďte opatrní a dodržujte následující pravidla:
- Zadejte správný počet argumentů a ve správném pořadí.
- V ideálním případě by argumenty měly mít přesně stejné datové typy jako odpovídající parametry. Datový typ každého argumentu se musí v každém případě rozšířit na datový typ odpovídajícího parametru. To platí i v případě, že je příkaz Option Strict nastavený na
Off
hodnotu . Pokud přetížení vyžaduje zužující převod ze seznamu argumentů, není možné ho volat. - Pokud zadáte argumenty, které vyžadují rozšíření, nastavte jejich datové typy co nejblíže odpovídajícím datovým typům parametrů. Pokud dvě nebo více přetížení přijímají datové typy argumentů, kompilátor přeloží volání na přetížení, které volá nejmenší míru rozšíření.
Riziko neshody datových typů můžete snížit použitím klíčového slova převodu funkce CType při přípravě argumentů.
Selhání řešení přetížení
Při volání přetížené procedury se kompilátor pokusí odstranit všechny přetížení kromě jednoho. Pokud se to podaří, přeloží volání na toto přetížení. Pokud eliminuje všechna přetížení nebo pokud nemůže snížit způsobilé přetížení na jednoho kandidáta, vygeneruje chybu.
Následující příklad znázorňuje proces řešení přetížení:
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)
Při prvním volání kompilátor eliminuje první přetížení, protože typ prvního argumentu (Short
) se zužuje na typ odpovídajícího parametru (Byte
). Potom eliminuje třetí přetížení, protože každý typ argumentu v druhém přetížení (Short
a Single
) se rozšiřuje na odpovídající typ třetího přetížení (Integer
a Single
). Druhé přetížení vyžaduje méně rozšíření, takže ho kompilátor použije pro volání.
Při druhém volání kompilátor nemůže eliminovat žádné přetížení na základě zúžení. Eliminuje třetí přetížení ze stejného důvodu jako v prvním volání, protože může volat druhé přetížení s menším rozšířením typů argumentů. Kompilátor však nemůže přeložit mezi prvním a druhým přetížením. Každý má jeden definovaný typ parametru, který se rozšiřuje na odpovídající typ v druhém parametru (Byte
na Short
, ale Single
na Double
). Kompilátor proto vygeneruje chybu řešení přetížení.
Správný přístup: Chcete-li volat přetíženou proceduru bez nejednoznačnosti, použijte funkci CType k porovnání datových typů argumentů s typy parametrů. Následující příklad ukazuje volání, které vynutí z
rozlišení na druhé přetížení.
Call z(CType(p, Short), CType(q, Single))
Rozlišení přetížení s volitelnými argumenty a argumenty ParamArray
Pokud dvě přetížení procedury mají stejné podpisy kromě toho, že poslední parametr je deklarován volitelný v jednom a ParamArray v druhé, kompilátor přeloží volání této procedury podle nejbližší shody. Další informace najdete v tématu Řešení přetížení.