Lathund - Variablers och konstanters räckvidd
Förord
Räckvidden för variabler och konstanter bestäms av två faktorer:- Om man deklarerar i huvudet av en procedur, formulärmodul eller standardmodul.
- Om man skriver Public respektive Public Const istället för Dim respektive Const.
Innehåll
»»
»
»
»
»
»
»
»
Relaterade artiklar
» Lathund - API-anrop» Lathund - Arrayer, egna datatyper och numreringar
» Lathund - Databaser
» Lathund - Felhantering
» Lathund - Grundläggande syntax
» Lathund - Inbyggda funktioner
» Lathund - Klassmoduler
» Lathund - Kortkommandon
» Lathund - Namngivning och deklarationer
» Lathund - Några extra tips
» Lathund - Slingor och operatorer
» Lathund - Spara, öppna och skriva ut filer
Variablers och konstanters räckvidd
Om man vill skapa en lokal variabel eller konstant, som bara kan användas i en viss procedur, så deklarerar man variabeln eller konstanten som vanligt i procedurens huvud och använder uttrycken Dim respektive Const.Om man vill skapa en modulär variabel eller konstant, som kan användas i alla procedurer i en viss modul, så deklarerar man i modulens huvud och skriver Private respektive Private Const. (De vanliga uttrycken Dim respektive Const går också bra.)
Exempel:
Private m_strCompany As String
Private Const m_strCity As String = "Stockholm"
Ibland vill man skapa en global variabel eller konstant, som kan användas i alla procedurer i hela projektet. Då måste man deklarera i huvudet av en standardmodul och skriva Public respektive Public Const istället för Dim respektive Const. (I Visual Basic 3.0 använde man inte ordet Public, utan Global. Det fungerar fortfarande, men rekommenderas inte.)
Exempel:
Public p_strCompany As String
Public Const p_intBonus As Integer = 500
Lägg märke till att man brukar hänga på ett m_ (för modular) respektive ett p_ (för public) framför namnet på modulära respektive globala variabler och konstanter. Det kan verkligen rekommenderas, särskilt i större projekt med många moduler, för det är mycket bra att kunna se variabelns räckvidd på variabelnamnet. (I Visual Basic 3.0 brukade man använda bokstaven g istället för p.)
VARNING!
Använd inte för många globala variabler, särskilt inte i större projekt med många moduler. Annars blir det väldigt mycket hoppande fram och tillbaka med Shift+F2 och Ctrl+Shift+F2 för att kontrollera vad den och den globala variabeln heter.
I princip har globala variabler varit onödiga sedan Visual Basic 4.0, då klassmoduler infördes. Istället för att använda globala variabler kan man skapa en klass, vars egenskaper ersätter de globala variablerna. (Se avsnittet Klassmoduler.) Du kommer att märka att det har flera fördelar. Naturligtvis måste man skapa en global instans av klassen, så att dess egenskaper kan nås från alla moduler i projektet.
Ett annat alternativ är att definiera en egen datatyp som innehåller alla globala variabler och sedan deklarera en enda global variabel med denna datatyp. Skriv alltså inte så här:
Public p_strA As String
Public p_intB As Integer
Public p_lngC As Long
Public p_sngD As Single
Public p_dblE As Double
Skriv så här istället:
Public Type ExPublics
A As String
B As Integer
C As Long
D As Single
E As Double
End Type
Public p_Pub As ExPublics
Nu slipper du att hoppa fram och tillbaka med Shift+F2 och Ctrl+Shift+F2 för att kontrollera vad den och den globala variabeln heter. Så fort du skriver p_Pub följt av en punkt dyker det upp en lista över alla dina (före detta) globala variabler!
Onödig räckvidd
"Excess scope" är ett misstag som programmerare ofta gör i Visual Basic. Det skulle kunna översättas med "onödig räckvidd". Vad det handlar om är globala variabler som lika gärna kunde vara modulära, eftersom de ändå bara används i en enda modul, eller t o m lokala, eftersom de bara används i en enda procedur. Programmeraren trodde kanske att variabeln skulle komma till användning i flera moduler, men glömde sedan att kolla om så verkligen blev fallet.Onödig räckvidd försämrar programmets prestanda och bör därför undvikas. Även procedurer kan ha onödig räckvidd.
Döda variabler och konstanter
Döda variabler och konstanter är sådana som deklareras utan att användas. De bör naturligtvis undvikas, eftersom de komplicerar koden i onödan och försämrar programmets prestanda. Döda procedurer är ännu värre.Att försöka hitta alla döda variabler, konstanter och procedurer i ett färdigt program är tidsödande. Att försöka hitta alla som har onödig räckvidd är ännu besvärligare. Därför är det bra att det finns program som gör jobbet automatiskt, t ex Project Analyzer från Aivosto.
Inbyggda konstanter
I Visual Basic finns det hundratals inbyggda konstanter för alla möjliga ändamål. Deras namn börjar alltid med bokstäverna vb och deras datatyp brukar vara Long eller Integer.Det finns t ex två inbyggda konstanter som heter vbYes och vbNo och har datatypen Integer. Värdet av vbYes är 6. Värdet av vbNo är 7. Vad är vitsen med detta? Jo, den inbyggda funktionen MsgBox, som visar en meddelanderuta, har returvärdet 6 om användaren klickar på knappen Ja i meddelanderutan. Om användaren klickar på knappen Nej har funktionen returvärdet 7. För att man ska slippa komma ihåg talen 6 och 7 kan man istället använda konstanterna vbYes och vbNo. Dessutom finns det en inbyggd konstant som heter vbYesNo och har värdet 4. Den används som argument nummer två i funktionen MsgBox när man vill visa en meddelanderuta med två knappar, en för Ja och en för Nej. Det finns förstås andra inbyggda konstanter som ger andra knappar, t ex vbOKCancel, som ger en knapp för OK och en för Avbryt.
Public Function IsSmart() As Boolean
Dim intReturn As Integer
intReturn = MsgBox("Can you write Visual Basic code?", vbYesNo)
If intReturn = vbYes Then
IsSmart = True
Else
IsSmart = False
End If
End Function
Variablers livslängd
Variablers livslängd beror på deras räckvidd.Lokala variabler förlorar sitt värde när proceduren avslutas. Om man ersätter uttrycket Dim med ordet Static behåller variabeln sitt värde när proceduren avslutas, men är fortfarande lokal.
Modulära variabler som deklareras i huvudet av en formulärmodul förlorar sitt värde när programmet avslutas eller när man använder satsen
Set frmMyForm = Nothing
om vi antar att det aktuella formuläret har namnet frmMyForm. Observera att det inte räcker att ladda ur formuläret om man vill att en modulär variabel ska förlora sitt värde.
Globala variabler förlorar aldrig sitt värde förrän programmet avslutas.
Procedurer och deras räckvidd
Från början fanns det två sorters procedurer i Visual Basic: funktioner, som anges med uttrycket Function, och subrutiner, som anges med uttrycket Sub. Sedan Visual Basic 4.0 finns det en tredje sort, egenskapsprocedurer, se avsnittet Klassmoduler.Händelseprocedurer är subrutiner som körs när en viss händelse äger rum för ett visst objekt, t ex när användaren klickar på en knapp.
VARNING!
Ett vanligt misstag är att skriva händelseprocedurer för fel händelser. Ett annat vanligt misstag är att skriva händelseprocedurer för rätt händelser, men i fel ordning.
När man skriver händelseprocedurer i Visual Basic är det avgörande viktigt att man förstår vilka händelser som kan inträffa för ett visst objekt, t ex en knapp eller ett formulär, när händelserna inträffar och i vilken inbördes ordning de inträffar. När man t ex laddar ett formulär inträffar händelserna Initialize, Load och Activate för formuläret, i den ordningen. När man laddar ur ett formulär inträffar händelserna QueryUnload, Unload och Terminate för formuläret, i den ordningen.
Den väsentliga skillnaden mellan funktioner och subrutiner är att funktioner har argument och returvärde, medan subrutiner bara har argument. En annan skillnad är att man sätter argumenten inom parentes när man anropar funktioner. När man anropar subrutiner sätter man inte argumenten inom parentes. (Om man anropar subrutinen med uttrycket Call eller om subrutinen endast har ett argument tillåter Visual Basic att man sätter argumenten inom parentes när man anropar subrutinen.)
Ett exempel på hur man skriver en funktion:
Function Add(intA As Integer, Optional intB As Integer) As Long
Add = intA + intB
End Function
Vad händer om man skriver
lngNumber = Add(3)
och utelämnar det frivilliga argumentet intB? Kraschar programmet? Nej, kom ihåg vad du läste om variablers startvärden i avsnittet Deklaration av variabler och konstanter. Startvärdet för alla variabler med datatypen Integer är 0. Eftersom intB inte tilldelas något värde i exemplet ovan gäller att intB = 0.
Om man vill att det frivilliga argumentet intB ska få ett annat värde än 0 när argumentet utelämnas, t ex 5, kan man skriva
Function Add(intA As Integer, Optional intB As Integer = 5) As Long
Add = intA + intB
End Function
När ett frivilligt argument har datatypen Variant kan man använda funktionen IsMissing för att kontrollera om argumentet har utelämnats:
Function Multiply(intA As Integer, Optional vntB As Variant) As Long
If IsMissing(vntB) Then
Multiply = 5 * intA
MsgBox "Hallå, du angav inte värdet på argumentet vntB!"
Else
Multiply = 5 * intA
MsgBox "Jaså, du tyckte att argumentet vntB skulle ha värdet " & vntB
End If
End Function
De argument som man skriver ordet Optional framför måste stå sist i argumentlistan. Optional kan inte användas om argumentet är en array eller egen datatyp. Man kan heller inte använda Optional om det finns en ParamArray bland argumenten.
Funktioner kan avbrytas i förtid med satsen Exit Function, subrutiner med Exit Sub.
VARNING!
Att vara okunnig om funktionen DoEvents kan vålla problem för Visual Basic-programmerare. Ibland är det nödvändigt att använda denna funktion. DoEvents pausar programmet en liten bråkdel av en sekund, så att operativsystemet hinner med allt som programmet hittills har bett om. För det mesta hinner operativsystemet med allting i tid utan DoEvents och man ska inte använda denna funktion i onödan, men ibland är det nödvändigt.
VARNING!
Undersökningar har visat att procedurer som är längre än 500 rader medför en kraftigt ökad risk för missförstånd. Skriv inte så långa procedurer, utan dela dem i flera mindre procedurer.
Sanningen om procedurernas räckvidd
Om man vill skapa en global procedur, som kan anropas från alla andra procedurer i hela projektet, är det nödvändigt att placera proceduren i en standardmodul eller klassmodul (se avsnittet Klassmoduler). En formulärmodul duger inte.Man behöver inte använda ordet Public när man skapar globala procedurer i standardmoduler och klassmoduler, men det är en god vana att ändå göra det, särskilt i klassmoduler, för tydlighets skull.
Ordet Private får naturligtvis inte användas, för då kan proceduren endast anropas från andra procedurer i samma standardmodul eller klassmodul.
Sanningen om parenteserna
Det händer att man vill anropa en funktion, fast man inte är intresserad av returvärdet. Då märker man vilket snällt språk Visual Basic är! Det är bara att slopa parenteserna runt argumenten när man anropar funktionen, så slipper man ta hand om returvärdet!
MsgBox "Returvärdet är 1, men det struntar vi i", vbOKOnly
Alternativt kan man använda uttrycket Call:
Call MsgBox("Returvärdet är 1, men det struntar vi i", vbOKOnly)
När man anropar en procedur med uttrycket Call måste man alltid sätta argumenten inom parentes och man får aldrig något returvärde, varken från funktioner eller subrutiner.
Sanningen om ByVal och ByRef
När man skapar en procedur kan man använda orden ByVal eller ByRef framför vart och ett av argumenten i argumentlistan. Om man skriver ByVal kan proceduren inte påverka värdena av de variabler som den anropande proceduren skickar som argument. Så kan dock bli fallet om man skriver ByRef:
Public Function Kubik(ByRef lngA As Long) As Long
lngA = lngA ^ 3
Kubik = lngA
End Function
Att varken skriva ByVal eller ByRef är samma sak som att skriva ByRef. (Den som använder Delphi eller Visual Basic .NET får vänja sig vid motsatsen. I Delphi skriver man dock inte ByRef, utan var. Istället för ByVal skriver man ingenting. Det är bra att Visual Basic .NET har fått liknande regler.)
Läroböcker i Visual Basic 5.0 och 6.0 brukar missa ett undantag: Om man sätter parenteser runt argumentet när man anropar en subrutin (man får som sagt lov att sätta parenteser runt argumentet utan att använda uttrycket Call om subrutinen endast har ett argument) tror Visual Basic att man har skrivit ByVal, oavsett om man har skrivit ByRef, ByVal eller ingenting! Undantaget gäller endast när man anropar en subrutin utan att använda utrycket Call.
Om man använder en array eller egen datatyp som argument kan man inte skriva ByVal framför.
Att skriva ByRef är ett sätt att skapa en funktion som indirekt returnerar flera värden. Om man inte är intresserad av det (och det är man för det mesta inte) har man ingen anledning att använda ByRef.
Att skriva ByVal förbättrar det färdiga programmets prestanda. Använd ByVal så mycket som det någonsin går!
VARNING!
När en variabel används som argument vid ett proceduranrop ska argumentet inte ha samma namn i den anropande och den anropade proceduren. Om man bryter mot denna regel riskerar man att skriva mycket svårtolkad kod.
0 Kommentarer