Dela via


Felsökningsprocedurer (Visual Basic)

På den här sidan visas några vanliga problem som kan uppstå när du arbetar med procedurer.

Returnerar en matristyp från en funktionsprocedur

Om en Function procedur returnerar en matrisdatatyp kan du inte använda namnet Function för att lagra värden i elementen i matrisen. Om du försöker göra detta tolkar kompilatorn det som ett anrop till Function. Följande exempel genererar kompilatorfel:

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

AllOnes(i) = 1 Instruktionen genererar ett kompilatorfel eftersom det verkar anropa AllOnes med ett argument av fel datatyp (en skalär Integer i stället för en Integer matris). Return AllOnes() Instruktionen genererar ett kompilatorfel eftersom det verkar anropa AllOnes utan argument.

Rätt metod: Om du vill kunna ändra elementen i en matris som ska returneras definierar du en intern matris som en lokal variabel. Följande exempel kompileras utan fel:

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

Argumentet har inte ändrats av proceduranrop

Om du tänker tillåta att en procedur ändrar ett programmeringselement som ligger till grund för ett argument i den anropande koden måste du skicka det med referens. Men en procedur kan komma åt elementen i ett referenstypargument även om du skickar det efter värde.

  • Underliggande variabel. Om du vill tillåta att proceduren ersätter värdet för själva det underliggande variabelelementet måste proceduren deklarera parametern ByRef. Dessutom får den anropande koden inte omsluta argumentet inom parentes, eftersom det skulle åsidosätta överföringsmekanismen ByRef .

  • Referenstypelement. Om du deklarerar en parameter byval kan proceduren inte ändra själva det underliggande variabelelementet. Men om argumentet är en referenstyp kan proceduren ändra medlemmarna i objektet som det pekar på, även om det inte kan ersätta variabelns värde. Om argumentet till exempel är en matrisvariabel kan proceduren inte tilldela en ny matris till den, men den kan ändra ett eller flera av dess element. De ändrade elementen återspeglas i den underliggande matrisvariabeln i den anropande koden.

I följande exempel definieras två procedurer som tar en matrisvariabel efter värde och fungerar på dess element. Proceduren increase lägger helt enkelt till en till varje element. Proceduren replace tilldelar en ny matris till parametern a() och lägger sedan till en till varje element. Omtilldelningen påverkar dock inte den underliggande matrisvariabeln i den anropande koden eftersom a() deklareras 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

I följande exempel görs anrop till increase och 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)))

Det första MsgBox anropet visar "After increase(n): 11, 21, 31, 41". Eftersom n är en referenstyp increase kan ändra dess medlemmar, även om den skickas ByVal.

Det andra MsgBox anropet visar "After replace(n): 11, 21, 31, 41". Eftersom n skickas ByValreplace kan inte ändra variabeln n genom att tilldela en ny matris till den. När replace skapar den nya matrisinstansen k och tilldelar den till den lokala variabeln aförlorar den referensen till n som skickas av den anropande koden. När det ökar medlemmarna ai påverkas endast den lokala matrisen k .

Rätt metod: Om du vill kunna ändra ett underliggande variabelelement i sig skickar du det med referens. I följande exempel visas ändringen i deklarationen för replace som gör att den kan ersätta en matris med en annan i den anropande koden:

Public Sub replace(ByRef a() As Long)

Det går inte att definiera en överlagring

Om du vill definiera en överbelastad version av en procedur måste du använda samma namn men en annan signatur. Om kompilatorn inte kan skilja deklarationen från en överlagring med samma signatur genererar den ett fel.

Signaturen för en procedur bestäms av procedurnamnet och parameterlistan. Varje överlagring måste ha samma namn som alla andra överlagringar men måste skilja sig från dem alla i minst en av de andra komponenterna i signaturen. Mer information finns i Överlagring av procedurer.

Följande objekt, även om de gäller parameterlistan, är inte komponenter i en procedurs signatur:

  • Nyckelord för procedurmodifierare, till exempel Public, Sharedoch Static.
  • Parameternamn.
  • Nyckelord för parametermodifierare, till exempel ByRef och Optional.
  • Datatypen för returvärdet (förutom en konverteringsoperator).

Du kan inte överbelasta en procedur genom att bara variera ett eller flera av föregående objekt.

Rätt metod: För att kunna definiera en överlagring av proceduren måste du variera signaturen. Eftersom du måste använda samma namn måste du variera parametrarnas antal, ordning eller datatyper. I en allmän procedur kan du variera antalet typparametrar. I en konverteringsoperator (CType-funktion) kan du variera returtypen.

Överlagringsmatchning med valfria argument och ParamArray-argument

Om du överbelastar en procedur med en eller flera valfria parametrar eller en ParamArray-parameter måste du undvika att duplicera någon av de implicita överlagringarna. Mer information finns i Överväganden i Överlagringsprocedurer.

Anropa fel version av en överbelastad procedur

Om en procedur har flera överlagrade versioner bör du vara bekant med alla deras parameterlistor och förstå hur Visual Basic löser anrop bland överlagringarna. Annars kan du anropa en annan överlagring än den avsedda.

När du har fastställt vilken överlagring du vill anropa bör du följa följande regler:

  • Ange rätt antal argument och i rätt ordning.
  • Helst bör dina argument ha exakt samma datatyper som motsvarande parametrar. I vilket fall som helst måste datatypen för varje argument utvidgas till motsvarande parameter. Detta gäller även med alternativet Strikt -instruktion inställt på Off. Om en överlagring kräver en begränsad konvertering från argumentlistan är den överlagringen inte berättigad att anropas.
  • Om du anger argument som kräver breddning gör du deras datatyper så nära motsvarande parameterdatatyper som möjligt. Om två eller flera överlagringar accepterar dina argumentdatatyper löser kompilatorn anropet till den överlagring som kräver minst breddning.

Du kan minska risken för att datatypen matchar fel med hjälp av nyckelordet CType-funktionskonvertering när du förbereder argumenten.

Problem med överlagringsmatchning

När du anropar en överbelastad procedur försöker kompilatorn eliminera alla överlagringar utom en. Om det lyckas löser det anropet till den överlagringen. Om den eliminerar alla överlagringar, eller om den inte kan minska de berättigade överlagringarna till en enda kandidat, genererar den ett fel.

I följande exempel visas processen för överbelastningsmatchning:

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)

I det första anropet eliminerar kompilatorn den första överlagringen eftersom typen av det första argumentet (Short) begränsas till typen av motsvarande parameter (Byte). Den eliminerar sedan den tredje överlagringen eftersom varje argumenttyp i den andra överlagringen (Short och Single) ökar till motsvarande typ i den tredje överlagringen (Integer och Single). Den andra överlagringen kräver mindre breddning, så kompilatorn använder den för anropet.

I det andra anropet kan kompilatorn inte eliminera någon av överlagringarna på grundval av förträngning. Den eliminerar den tredje överlagringen av samma anledning som i det första anropet, eftersom den kan anropa den andra överlagringen med mindre breddning av argumenttyperna. Kompilatorn kan dock inte matcha mellan den första och andra överlagringen. Var och en har en definierad parametertyp som utvidgas till motsvarande typ i den andra (Byte till Short, men Single till Double). Kompilatorn genererar därför ett överlagringsmatchningsfel.

Rätt metod: Om du vill kunna anropa en överbelastad procedur utan tvetydighet använder du CType-funktionen för att matcha argumentdatatyperna med parametertyperna. I följande exempel visas ett anrop till z som tvingar upplösningen till den andra överlagringen.

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

Överlagringsmatchning med valfria argument och ParamArray-argument

Om två överlagringar av en procedur har identiska signaturer förutom att den sista parametern deklareras som Valfri i den ena och ParamArray i den andra, löser kompilatorn ett anrop till den proceduren enligt den närmaste matchningen. Mer information finns i Överlagringsmatchning.

Se även