Sdílet prostřednictvím


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ů aná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, Shareda Static.
  • Názvy parametrů.
  • Klíčová slova modifikátoru parametrů, například ByRef a Optional.
  • 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 Offhodnotu . 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í.

Viz také