Hauptseite >Tips zu VB5/6 >  Leerer String vs. vbNullString
 
Zitat aus der VB5-Hilfe zur Dim-Anweisung: "Bei der Initialisierung wird [...] Zeichenfolgen variabler Länge eine Null-Zeichenfolge ("") zugewiesen."

Probieren wir es aus:

Dim x as String, l As Long
Debug.Print x = ""             ' => ergibt True
Debug.Print x = vbNullString   ' => ergibt True
Debug.Print "" = vbNullString  ' => ergibt True
            
Scheint alles zu stimmen. Seltsam ist aber folgendes:

Debug.Print StrPtr(x) ' => ergibt 0
x = ""
Debug.Print StrPtr(x) ' => ergibt irgendwas > 0
x = vbNullString
Debug.Print StrPtr(x) ' => ergibt 0
            
Sollte es da doch einen Unterschied geben?
Legen wir zum Test eine Datei "test.ini" mit folgendem Inhalt an:

[Section1]
Entry1=Value1
Entry2=Value2

und lassen die Funktion WritePrivateProfileString() auf diese Datei los:

x = vbNullString
l = WritePrivateProfileString("Section1", "Entry1", x, "test.ini")
x = ""
l = WritePrivateProfileString("Section1", "Entry2", x, "test.ini")
            
Danach sieht es in "test.ini" so aus:

[Section1]
Entry2=

Die Zeile mit Entry1 ist verschwunden! Fazit: Es gibt einen Unterschied.

Im Prinzip ist ein String mit einem Objekt vergleichbar (Genaueres hierzu findet man in diesem MSDN-Artikel). Bei der Deklaration mit Dim wird ein Zeiger (Long-Wert, der die Speicheradresse des Objekts enthält) angelegt; da das Objekt selbst aber noch nicht existiert, erhält der Zeiger den Wert 0. Dasselbe passiert, wenn mit
              
Dim n As MeineKlasse
            
ein "echtes" Objekt deklariert wird. Der Zeiger wird zwar angelegt, aber ohne das Schlüsselwort New gibt es noch kein Objekt. Folglich kann auch auf dessen Eigenschaften und Methoden noch nicht zugegriffen werden:
              
Debug.Print n.Text  ' => Laufzeitfehler!
            
Mit If n Is Nothing Then ... findet man leicht heraus, ob ein Objekt instanziiert ist oder nicht; ist es nicht instanziiert, setzt es einen Laufzeitfehler, wenn man dennoch auf seine Eigenschaften oder Methoden zuzugreifen versucht.

Anders beim String: Wenn man den Wert eines Strings abfragt (Debug.Print x), wird eigentlich eine Funktion der String-Instanz aufgerufen. Es gibt aber keinen Laufzeitfehler, wenn dieser String noch gar nicht existiert! Hier mogelt VB und gaukelt vor, der Zeiger repräsentiere ein gültiges String-Objekt der Länge 0:

x = vbNullString
Debug.Print Len(x)  ' => ergibt 0, stimmt aber eigentlich nicht, denn
                    '    der String ist nicht initialisiert, d.h. der
                    '    Wert müsste undefiniert sein
x = ""
Debug.Print Len(x)  ' => ergibt 0, stimmt
            
Das ist innerhalb der Grenzen von VB alles gar kein Problem. Wird der uninitialisierte String aber ans API übergeben, kann sich VB nicht "erklärend zwischenschalten", und es kommt zu seltsamen Effekten, im schlimmsten Fall zu einer Schutzverletzung. Das unterschiedliche Verhalten von WritePrivateProfileString() ist damit auch erklärt:

x = vbNullString
l = WritePrivateProfileString("Section1", "Entry1", x, "test.ini")
            
Es wird ein Null-Zeiger übergeben; per Definition löscht dies den Eintrag.

x = ""
l = WritePrivateProfileString("Section1", "Entry2", x, "test.ini")
            
Es wird ein Zeiger auf einen String der Länge 0 uebergeben; folglich bleibt der Eintrag erhalten, nur der Wert wird zurückgesetzt.

Die einzig sichere Methode, zu entscheiden, ob ein String "" oder vbNullString ist, ist die StrPtr()-Funktion, die den Wert des String-Zeigers zurückliefert. Leider hat Microsoft diese Funktion nicht dokumentiert. Und der eingangs zitierte Satz aus der Online-Hilfe von VB5 zur Dim-Anweisung ist definitiv ebenso falsch wie die im Objekt-Katalog enthaltene Definition Const vbNullString = "". Hier werden Fakten verschleiert, die im Umgang mit dem API von grosser Bedeutung sein können.
Hauptseite >  Tips zu VB5/6 >  diese Seite