Re: Boolean-Variable per default auf FALSE?
- From: "Peter Götz" <gssg_nospam@xxxxxxxxxxx>
- Date: Sun, 10 Jun 2007 17:48:41 +0200
Hallo Alexander,
Wenn Du einen Wert vom Typ Boolean haben willst,
dann verwende auch einen solchen. Ein Variant ist
kein Boolean, er kann einen beinhalten.
Wenn er angeblich einen beinhaltet, geht man
davon aus, dass der einen von zwei Zuständen hat.
Ja, genau das hat er auch, nämlich False oder True.
Wie wir seit geraumer Zeit wissen kennt ein Boolean
aber 65535 Zustände,
Falsch!
Er kennt
False (=0)
und
True (<>0)
Das sind zwei Zustände und nicht 65535.
obwohl das, was mindestens den Variant-Boolean angeht,
Was reitest Du immer auf Deinem Variant-Boolean herum?
Ein Variant kann alles mögliche, eben auch einen Wert
vom Typ Boolean aufnehmen. Das heisst aber nicht,
dass man diesen Variant, wenn man nun schon mal weiss,
dass es sich um einen Wert vom Typ Boolean handelt,
ständig als Variant herumschleppt.
Der Variant macht Sinn, als Parameter, bei dem erst
mal der zu übergebende Datentyp unbestimmt ist.
Die Prozedur (Sub/Function) welche diesen Variant übernimmt
kann prüfen, welchen Datentyp sie wirklich bekommen hat
und genau dafür eine typgerecht deklarierte Variable
bereitstellen.
nach der COM-Spezifikation eigentlich ungültig ist.
Die APIs die VariantChanges handeln, sollten sicherstellen, dass ein
VT_BOOL nur 0x0000 oder 0xFFFF ist, bzw das worauf er zeigt
wenn es ein VT_BYREF ist.
Sie sollen, wenn sie denn dafür konzipiert sind, Werte
aus VB-Code zu erhalten den erhaltenen Variant einer
typgerecht deklarierten Variablen übergeben und
damit "!!! typgerecht !!!" weiterarbeiten.
Wenn Du von irgendwoher einen Variant mit einem
Inhalt ungleich 0 geliefert bekommst und in Deinem
Programmcode diesen Wert als Typ Boolean
weiterverarbeiten willst dann schreibe
dim variantVar as Variant
variantVar = 1234567
dim boolVar as Boolean
boolVar = variantVar
So und nicht anders.
Wieso nicht anders?
Weil das eine typgerechte Arbeitsweise ist, die
Missverständnisse und unerwartete Typumwandlungen
von vorne herein ausschliesst.
Wenn die Sprache neben einer direkten Zuweisung auch
eine ByRef-Zuweisung kennt, geht es syntaktisch auch anders.
Das heisst aber doch nicht, dass man einen ByRef übergebenen
Parameter im Anschluss nicht typgerecht weiterbearbeiten
könnte.
Man kann mit einem Auto langsam oder schnell, vorwärts
oder rückwärts fahren, es hindert einen aber auch nichts
daran mit dem Vehikel gegen den nächsten Baum zu
fahren, egal ob vorwärts, rückwärts, langsam oder schnell.
Und ich frage Dich, was hat das ganze mit ByRef zu tun.
Auch wenn ich in einem ByRef-Parameter einen Wert als
Variant übergeben bekomme, zwingt mich nichts, mit
diesem Variant weiterzuwurschteln. Ich ermittle den
tatsächlichen Typ und übergeben den Wert einer
passenden Variablen. Nach der Ver- und Bearbeitung
dieser Variablen kann man das Ergebnis wieder dem
ByRef Paramter (Variant) übergeben und die Rückgabe
ist damit wie gewünscht erfolgt.
In konkretem Code würde das etwa so aussehen:
Private Sub AnySub1(ByRef Wert As Variant)
Dim BW As Boolean
Select Case VarType(Wert)
Case vbBoolean
BW = Wert
' selbst der nachfolgende Or-Unsinn
' könnte nun keinen Schaden mehr
' anrichten.
BW = BW Or 6
Wert = BW
Exit sub
Case Else
' tu was anderes mit Wert
End Select
End Sub
Da das nicht als unsupported, deprectaed oder dergleichen
markiert ist, sollte es verwendbar sein.
Es steht aber nirgendwo in der VB-Dokumentation
das man für jeden tauglichen oder untauglichen Zweck
Variants verwenden soll.
Etliche APIs geben Variants zurück.
Ja und?
Mit VarTyp() oder TypeName() lässt sich feststellen
was in dem Variant wirklich steckt und damit kann man
den im Variant erhaltenen Wert einer typgerecht
deklarierten Variablen zur weiteren Verarbeitung
übergeben.
Wenn man sich ein generischen Wrapper baut
(generisch-> ergo Variant-Rückgabe), um aus
ADO-Feldern den Wert zu extrahieren, schnappt
so eine Falltür schneller auf als man es für möglich
hält.
Auch da hindert einen nichts und niemand daran
typgerecht zu arbeiten.
Ansonsten wüsste ich nicht so recht, welches
konkrete Problem Du damit meinen könntest.
Schau Dir mal
www.gssg.de -> Visual Basic -> VBclassic
-> Datenbank -> ADO DemoMU2002
an. In frmMain Function DoUpdate() wird genau so
eine Übergabe eines Datensatzes via VariantArray
an ein Recordset in clsGSADOData Function DoUpdate
gemacht. "Wo" sollte dabei "was" passieren?
Wenn Du in Deinem Programmablauf weiter mit
dem Variant herumwurschtelst und möglicherweise
irgendwann gar nicht mehr weist, welchen
Datentyp Du damit haben wolltest, ist das nicht
die Schuld von VB.
Doch, die Schuld von VB ist, dass es bei zu grosszügig
Variant ByRef-Übergaben zulässt, die undefiniertes Verhalten nach
sich ziehen.
Die ziehen kein undefiniertes Verhalten nach sich, wenn
man anschliessend typgerecht weiterarbeitet.
Ist es denn ein undefiniertes Verhalten des Autos, wenn Du
damit gegen einen Baum fährst und dabei
zumindest einige blaue Flecken bekommst?
Zwischen String-Variants und Bool- oder numerischen
Variants lässt es das sinnvollerweise auch nicht zu.
sondern löst einen Fehler aus (sofern der String nicht "True, "False" oder
deren Lokalisierung ist).
Genau das sollte es bei bei der ByRef-Übergabe von boolschen
Aktualparameter an formale Variant-Parameter auch machen, wenn
die Argument-Werte nicht passen. E_INVALID_ARG zurückgeben.
Das sollte Dein Programmcode machen:
Option Explicit
Private Sub Form_Load()
Randomize
End Sub
Private Sub Form_Click()
Dim RndNumber As Integer
Dim strBuffer As String
Dim intWert As Integer
Dim bolWert As Boolean
RndNumber = Fix(6) * Rnd
On Error GoTo Fehler
Select Case RndNumber
Case Is > 3
intWert = 999
intWert = 999
AnySub intWert
MsgBox "Ergebnis: " & CStr(intWert), _
vbInformation
Case Is < 2
strBuffer = "wrzlbrmpft"
AnySub strBuffer
Case Else
bolWert = True
AnySub bolWert
If bolWert Then
strBuffer = "Schönes Wetter"
Else
strBuffer = "Kein schönes Wetter"
End If
MsgBox strBuffer, vbInformation
End Select
Exit Sub
Fehler:
With Err
strBuffer = "Fehler: " & CStr(.Number) & vbCrLf & _
"Source: " & .Source & vbCrLf & _
.Description
End With
MsgBox strBuffer, vbExclamation
End Sub
Private Sub AnySub(ByRef Wert As Variant)
Dim bolRet As Boolean
Dim intRet As Integer
Select Case VarType(Wert)
Case vbBoolean
If MsgBox("Ist heute schönes Wetter?", _
vbQuestion Or vbYesNo) = vbYes Then
bolRet = True
Else
bolRet = False
End If
Wert = bolRet
Case vbInteger
intRet = Wert
If MsgBox("Soll ich 3 addiieren?", _
vbQuestion Or vbYesNo) = vbYes Then
intRet = intRet + 3
End If
Wert = intRet
Case Else
Err.Raise 13, "AnySub"
End Select
End Sub
Und zwar genau weil VB selbst ein Konzept von
Bedingungsprüfungen hat,
Ein Variant kann aber nun mal per Definition jeden
anderen Datentyp aufnehmen. Auf welchen Typen
sollte VB also prüfen?
dass auf numerischen Werten und Bitlogik basiert
und nicht auf echter bool'sche Ja Nein Logik, ist es
wichtig, dass ein Boolean nur genau zwei intere
Stati kennt.
Genau die beiden Zustände hat der Typ Boolean ja
auch nur, eben False (=0) und True (<>0).
Man sollte eben einfach nicht den Typ Boolean mit
dem Typ Variant verwechseln.
dagegen nur der vt-Wert des Variant-structs
angepasst, der numerische Wert aber beibehalten (geht
schneller)
Er wird dann auch beim Cast von VT_BOOL zu BOOL
übernommen und geistert von da an in der Bool-Variable
als darunterliegender Integer-Wert herum.
Durch diese Lücke kann ein VB-Boolean dann doch andere
numerische Werte in sich tragen als -1 und 0
Was absolut nicht der Dokumentation zum Datentyp Boolean
widerspricht. Die Dokumentation nennt den Wert 0 eindeutig
als False und alles <> 0 als True.
NACK. Die Dokumentation sagt:
The True keyword has a value equal to -1.
Man sollte halt auch lesen was da wirklich steht.
Hier steht nichts vom Typ Boolean.
Hier steht schlicht und einfach dass das "Schlüsselwort"
True den Wert -1 liefert. "Schlüsselwort True" und
Datentyp "Boolean" sind, soweit ich als Bayer der
deutschen Sprache mächtig bin, aber eben zwei
verschiedene Dinge.
Das "alles ungleich 0 ist True", ist ein C-Ding.
Das ist kein C-Ding sondern das gilt per Definition
für den Datentyp Boolean in VB.
Einfach mal die Doku lesen und "Schlüsselwort True"
dabei nicht mit "Datentyp Boolean" verwechseln.
C kennt keinen Boolean&HFFFF.
Datentyp, da ist das Makro FALSE = 0 und TRUE = !FALSE, zumindestens
in der VC-Welt. In VB ist True aber als -1 definiert, um exakt zu sein
Soll die ganz Diskussion darum, ob man vor dem Programmieren
erst mal die Dokumentation des Programmwerkzeuges lesen
soll wieder von vorne beginnen?
Dokumentation, Runtime und Implementationsdetail stimmen eben
nicht 100% überein und bei dem Problemchen geht es um die
Entscheidung zugunsten des eine Designkonzepts, sorgloser
automatischer Konvertierung,
"Sorglose, automatische Konvertierung" hat in einem
prof. erstellten VB-Programm schlicht und einfach nichts
zu suchen. Wenn Hobbyisten ohne Option Explizit irgendwas
zusammenbasteln, sollen sie das tun. Solche Spielereien
würde ich aber nicht unbedingt als sauberes Programmieren
bezeichnen.
Den Rest Deines Postings will ich mal nicht mehr
weiter kommentieren, weil es doch immer wieder auf
das selbe hinausläuft.
Gruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen)
.
- Follow-Ups:
- Re: Boolean-Variable per default auf FALSE?
- From: Alexander Mueller
- Re: Boolean-Variable per default auf FALSE?
- References:
- Boolean-Variable per default auf FALSE?
- From: Mark Riemann
- Re: Boolean-Variable per default auf FALSE?
- From: Thorsten Albers
- Re: Boolean-Variable per default auf FALSE?
- From: Thorsten Doerfler
- Re: Boolean-Variable per default auf FALSE?
- From: Thorsten Albers
- Re: Boolean-Variable per default auf FALSE?
- From: Thorsten Doerfler
- Re: Boolean-Variable per default auf FALSE?
- From: Alexander Mueller
- Re: Boolean-Variable per default auf FALSE?
- From: Peter Götz
- Re: Boolean-Variable per default auf FALSE?
- From: Alexander Mueller
- Boolean-Variable per default auf FALSE?
- Prev by Date: Re: VB6-Setup-Programm legt Word2000-Makros lahm
- Next by Date: Re: VB6-Setup-Programm legt Word2000-Makros lahm
- Previous by thread: Re: Boolean-Variable per default auf FALSE?
- Next by thread: Re: Boolean-Variable per default auf FALSE?
- Index(es):
Relevant Pages
|