Variablen deklarieren

Hi
so wieder mal eine Frage, allerdings erstmal Interessehalber weil eine Änderung sehr umfangreich sein könnte.

Was ich bisher nie kapiert habe war die richtige Deklaration von Variablen.

Und zwar habe ich das bisher immer wahrscheinlich umständlich gemacht, es funktionierte aber *lol*.

Ich deklariere Variablen immer global.

Wenn ich in deine Subroutine gehe, habe ich am Anfang
Variable1, Variable2 usw. die jeweils auf 0 gestellt werden.

So innerhalb der Routine passieren verschiedene Sachen, welche eine Änderung der V

Hallo Werner,

Was ich bisher nie kapiert habe war die richtige Deklaration
von Variablen.

Man merkt es :wink:
Du hast dir da einen recht schlechten Stil angewöhnt.

Im ursprünglichen BASIC hatte man keine wahl, da gab es nur Globale Variablen.

So, fertig mit meckerm!

Globale Variablen sollte man sparsam verwenden und nur dann wenn es unbedingt nötig ist.

Das Problem ist, dass wenn diese irgendwo überschrieben wird, alle Programmteile betroffen sein können (Seiteneffekte).

Des weiteren wird der Code unübersichtlich:

  1. Die Variablennamen passen nicht zum Inhalt.
  2. Man weiss nie ob die Resultate weiterverwendet werden.
    Das wird dann ganz lustig, wenn man etwas ändern soll.

Also:
Erste Priorität ist, eine Variable lokal, also in der Prozedur, zu deklarieren.
Damit ist beim lesen des Programms schon klar, dass diese Variablen ausserhalb dieser Prozedur keine Gültigkeit haben.
Zudem musst man auch nicht mit den Namen aufpassen, du darfst in jeder Funktion eine Variable i als Schlaufenzähler verwenden ohne angst zu haben versehentlich einen unerwünschten Seiteneffekt zu erzeugen.

Muss eine Funktion Änderungen an eine lokalen Variablen durchführen übergibt man diese im Funktionsaufruf.
Hier gibt es dann zwei Möglichkeiten.
Entweder übergibt man einen Zeiger (ByRef) oder die Funktion liefert einen Rückgabewert welcher zugewiesen wird.
In jedem Fall ist aber im Aufruf dokumentiert, dass das so gewollt ist.

Ich arbeite hauptsächlich mit C, da hat man auch noch die Möglichkeit Parameter mit „const“ zu übergeben. Der Compiler erzeugt dann Fehlermeldungen, wenn eine entsprechende Variable versehentlich verändert werden soll. Zudem ist im Code auch dokumentiert, dass diese Prozedur diese Variable nicht verändert.

MfG Peter(TOO)

Autsch!

Entschuldige, aber es tut einem weh zu lesen, dass nur globale Variablen genutzt werden. Der jenige der dir das bei gebracht hat gehört… nunja belehrt.

Aber nun genug.

Du solltest möglichst alle Variable in deinem Sub deklarieren bsp::

Private Sub Button_click()
dim variable_1 as string

end sub

Die Variable_1 ist somit nur in diesem Sub gültig. Da das Sub auch noch Private ist, ist diese Subfunktion auch nur in diesem Modul gültig. D. h. Du könntest den Subnamen in einem anderen Modul erneut nutzen.

Möchstet du jedoch den Sub auch von außerhalb ansprechen können musst du es public machen.

Public sub button_click()
.
.
end sub

Des weiteren besteht noch die Möglichkeit der Parameter Rückgabe und übergabe.

D.h. willst du zum Beispiel dein Sub öfters aufrufen, weil eine Funktionalität öfters benötigt wird, jedoch sollen immer andere Werte verarbeitet werden, kannst du Parameter übergeben.

Beispiel:

Private Sub berechnen_click()

dim variable1 as integer
dim variable2 as integer
dim ergebnis as integer
variable1 = 1
variable2 = 2

ergebnis = Rechensub(variable1, variable2)

msgbox(„Das Ergebnis lautet“&ergebnis)

end sub

Private sub rechensub(var1 as integer, var2 as integer)

rechensub = var1 + var2

end sub

Der Wert der zurückgeben werden soll, wird dem Subnamen zugewiesen.

Dies ist nur ein einfaches Beispiel, wie man einen Sub aufruft, ihm Parameter übergibt und einen Returnwert zuweist.

Worauf du jedoch achten solltest, damit deine Variablen und Funktionsnamen immer so gelten wie du es deklariert hast, solltest du auf jeden Fall immer zum beginn deines Moduls : „Option Explicit“ schreiben.

Hoffe dir weiter geholfen zu haben und lass die Finger von globalen Variablen. Die sind *bäh*.

Nur zur Info am Rande: Leider sind unter VB keine Pointer möglich… die erleichtern die Arbeit ungemein :frowning: *heul*

Hallo Fragewurm,

Nur zur Info am Rande: Leider sind unter VB keine Pointer
möglich… die erleichtern die Arbeit ungemein :frowning: *heul*

Aber ByRef und ByVal kennst du ?

MfG Peter(TOO)

Hi
naja Schäm, kann vielleicht wirklich aus Basic Zeiten sein.

Die Frage ist, ob es sich lohnt alles umzustellen???
Danach geht evtl. weniger also vorher richtig.

Gibts hier Tools oder geht das mit der Suchfunktion, wenn man nur innerhalb der aktuellen Prozedur oder Modul sucht.

Das wäre wohl recht schwierig.

Das ByVal und ByRef hab ich auch noch nie gecheckt *lol*
Was macht das denn?

Ein Besipiel wäre immer ganz hilfreich dazu.

Mfg Werner

Hi

Hallo,

naja Schäm, kann vielleicht wirklich aus Basic Zeiten sein.

Die Frage ist, ob es sich lohnt alles umzustellen???

Je nachdem wie gross das Project ist nicht mehr! Wenn es denn von Nöten ist, ist man meist schneller das Project neu zu entwerfen :wink:

Danach geht evtl. weniger also vorher richtig.

Eben, einmal etwas übersehen und schon kann es maechtig vor dem Baum gehen und der Debugger ist ueber viele Tage dein bester Freund :frowning:

Gibts hier Tools oder geht das mit der Suchfunktion, wenn man
nur innerhalb der aktuellen Prozedur oder Modul sucht.

Das wäre wohl recht schwierig.

Das ByVal und ByRef hab ich auch noch nie gecheckt *lol*
Was macht das denn?

Einmal übergibst du den Wert direkt (ByVal)und einmal als Refernz(ByRef). Was das bedeutet weisst du sicherlich nicht.

Ich habe dazu mal einiges geschrieben. Aber nun gut dann eben noch einmal.

Unter VB gibt es einmal die primitiven Datentypen und dann noch Objecte.

Primitive Datentypen sind zum Bsp. Integer, Byte, Long etc.
Objecte sind zum Bsp. Klassen.

Vom Prinzip her kannst du dir merken. Alles wo du eine direkte Zuweisung machen kannst, sind Primitive Datentypen. Überall wo du Set verwendest oder New sind Object.

Nun stelle dir mal folgendes vor. Dein Speicher ist in 2 Teile unterteilt. Einmal den Stack und einmal den Heap.

Primitive Datentypen werden im Stack abgelegt. Objecte werden im Heap abgelegt. Bei Objecten kommt noch hinzu das im Stack ein Zeiger abgelegt wird. Er zeigt nur auf die Adresse im Heap wo sich das Object befindet.

Wenn du nun einen Wert als Referenz (ByRef)übergibst, so wird der Prozedur oder Function nur ein Zeiger auf den Wert übergeben. Das bedeutet aber das du diesen direkt ändern kannst!
Übergibst du stattdessen den Wert als ByVal, so wird im Stack eine Kopie des Wertes angelegt. In deiner Prozedur oder Function arbeitest du nur mit der Kopie. Beim verlassen der Prozedur oder der Function wird die Kopie gelöscht. Änderst du nun in der Prozedur oder Function den Wert, so ist er ergo nach verlassen der Prozedur oder Function wieder der selbe wie zu prozedure beginn.
Ein kleines Demo wird dies verdeutlichen.

Private Sub Command1\_Click()
Dim x As Integer, y As Integer
x = 10
y = 10
Test x, y
MsgBox "X (Byval):=" & x & vbTab & "Y /ByRef):=" & y
End Sub

Sub Test(ByVal a As Integer, ByRef b As Integer)
 a = 20
 b = 20
End Sub

Soweit ist das auch alles richtig, solange es um primitive Datentypen handelt. Anders ist das verhalten bei Objecten.
Da spielt ByRef und ByVal keine Rolle mehr. Da ja auf ein Zeiger im Stack zugegriffen wird. Über diesen Zeiger kommt man dann auf dem Heap. Das bedeutet, selbst wenn du den Wert als ByVal übergibst, so wird zwar eine Kopie vom Zeiger im Stack erstellt. Aber zugreifen tust du auf die Orginal Daten im Heap!

Private Sub Command1\_Click()
Dim MyData1 As New Class1, MyData2 As New Class1
MyData1.X = 10
MyData2.X = 10
Test MyData1, MyData2
MsgBox "Mydata (Byval):=" & MyData1.X & vbTab & "MyData /ByRef):=" & MyData2.X
End Sub

Sub Test(ByVal a As Class1, ByRef b As Class1)
 a.X = 20
 b.X = 20
End Sub

Die entsprechende Klasse würde dazu so ausschauen :wink:

Private MyData As Integer

Public Static Property Get X() As Integer
 X = MyData
End Property

Public Static Property Let X(ByVal vNewValue As Integer)
 MyData = vNewValue
End Property

Ein Besipiel wäre immer ganz hilfreich dazu.

Siehe oben :wink:

Mfg Werner

MfG Alex

2 Like

Hi
danke Anno,
hab mir den Text kopiert, und muss das mal testen mit den Beispielen.
Nur der Text ist etwas verwirrend, aber ich glaub das die Erklärung schon sehr gut ist.

Ich frage mich allerdings, was dagegen spricht alles global zu definieren. Im heutigen ZEitalter gibt es ja kaum noch Speicherprobleme.

Das einzige ist, das ich aufpassen muss, wegen der Übergabe der Variablen.

mfg Werner

Hi

Hallo Wernerm

danke Anno,

nichts zu danken :smile:

hab mir den Text kopiert, und muss das mal testen mit den
Beispielen.
Nur der Text ist etwas verwirrend, aber ich glaub das die
Erklärung schon sehr gut ist.

wieso verwirrend ? Ich habe versucht mich auf das wichtigste zu reduzieren. Ich haette auch viel weiter ausholen können :wink:

Ich frage mich allerdings, was dagegen spricht alles global zu
definieren. Im heutigen ZEitalter gibt es ja kaum noch
Speicherprobleme.

Das hat mit dem Speicher weniger zu tun, Werner.
Richtig ist das man zum Bsp. die Definition globaler Variablen in ein Modul auslagern koennte und somit haette man eigentlich alles im Überblick. Nun kommt aber das berühmte „ABER“

1:
Stelle dir mal vor, dein Project wächst und wächst. Du hast irgendwann mal 150 Formulare (Klingt viel, ist es aber net wirklich) und du bist fertig. 1 Jahr später sagst du dir … Mensch Werner, haette ich doch noch dies und das implementiert. Du nimmst dir also dein Project, kennst den Source net mehr und bist zu faul dich da reinzulesen. Du beginnst nun eine Routine nach der anderen zu schreiben. Dabei übergibst du eine Variable und beachtest nicht das sie schon einmal global declariert ist. Dein Project wird dann in compilierter Form nur noch spinnen und du findest dann den Fehler net so schnell

2: du schreibst fein brav deinen Source, achtest auf alles. irgendwann schreibst du ja auch Routinen in den Ereignissen. Dabei greifst du ja auch auf deine globalen Variablen zu.
Nehmen wir mal als Bsp. eine ZaehlerVariable I, die als Integer fungiert.
Wie schnell kann es nun passieren, das du dir die Variable überschreibst und ergo mit einen anderen Wert belegst?
Den Fehler dann zu finden, ist Wahnsinn!

3: Es ist unübersichtlich

4: Der Source wird schwerer zu verstehen sein

Das einzige ist, das ich aufpassen muss, wegen der Übergabe
der Variablen.

Unter anderem auch!

mfg Werner

MfG Alex