Zur Sinnhaftigkeit der Compilerwarnung BC42104 von Visual Basic .NET

Einleitung

Mit Visual Basic 8.0 wurde die neue Compilerwarnung BC42104 (Variable '<variablename>' is used before it has been assigned a value. A null reference exception could result at runtime.) eingeführt. Sie wird ausgelöst, wenn es zu einem lesenden Zugriff auf eine Variable eines Verweistyps mindestens einen Weg im Code gibt, auf dem der Variablen nicht explizit ein Wert zugewiesen wird. Diese Warnung ist aus mehreren Gründen in der Form, wie sie in Visual Basic 8.0 implementiert ist, kontraproduktiv. Einerseits kann ihr Auftreten mit geringem Aufwand vermieden werden, ohne dadurch die Qualität des Quellcodes zu erhöhen. Andererseits tritt die Warnung in Situationen auf, in denen der Zugriff auf eine implizit initialisierte Variable nicht notwendigerweise unbeabsichtigt zu einer NullReferenceException führt oder der Wert Nothing sogar erwünscht ist.

Problemfälle

Folgendes Listing zeigt ein Codebeispiel, in dem die Compilerwarnung BC42104 auftritt, da die Variable s nicht explizit initialisiert wurde und auf ein Instanzmitglied des Objekts, auf das sie verweist, zugegriffen wird. Visual Basic initialisiert Variablen, deren Typ ein Verweistyp ist, automatisch mit dem Wert Nothing. Die Variable wurde daher implizit initialisiert, obwohl der Beschreibungstext der Warnung gegenteiliges andeutet. Dennoch ist die Warnung in diesem Fall hilfreich, da bei der Ausführung des Codes sicher eine NullReferenceException auftreten wird.

Dim s As String

' BC42104.
s = s.ToLower()

Die einfachste Möglichkeit, die Warnung für eine Variable zu unterdrücken, besteht darin, die Variable explizit zu initialisieren. Dabei reicht es bereits aus, den Wert der Variablen bei deren Deklaration auf Nothing festzulegen. Das explizite Initialisieren der Variablen auf Nothing innerhalb der Variablendeklaration ist jedoch semantisch vollkommen gleichbedeutend mit einer Deklaration ohne explizite Initialisierung der deklarierten Variablen. Durch die explizite Initialisierung der Variablen hat sich an der Wahrscheinlichkeit des Auftretens einer Ausnahme des Typs NullReferenceException nichts verändert. Es ist lediglich der Code unnötig komplexer und umfangreicher geworden, nicht aber klarer, da die implizite Initialisierung der Variablen auf einen spezifizierten festen Wert in Visual Basic Tradition hat.

Dim s As String = Nothing
s = s.ToLower()

Im Wissen um die implizite Initialisierung von Variablen auf Nothing liegt daher nahe, den Wert der Variablen vor dem Zugriff auf ein Instanzmitglied des Objekts, auf das die Variable verweist, gegen Nothing zu testen. Zu diesem Zweck können die Operatoren Is und IsNot verwendet werden. Das nachstehende Listing zeigt ein Beispiel, in dem eine Variable in Abhängigkeit von einer Bedingung initialisiert wird oder sonst uninitialisiert bleibt. Da die Variable nicht garantiert initialisiert wird, soll vor dem Zugriff auf ein Instanzmitglied überprüft werden, ob die Variable auf ein Objekt verweist. Trotz der Überprüfung des Variablenwertes tritt die Warnung BC42104 auf, und zwar genau in jener Zeile, in welcher der Wert der Variablen mit Nothing verglichen wird. Beim Vergleich zweier Verweise kann jedoch keine Ausnahme vom Typ NullReferenceException auftreten. Der Beschreibungstext der Warnung ist wiederum unzutreffend, da Variable '<variablename>' is used before it has been assigned a value nicht aussagt, daß nicht sicher entschieden werden kann, ob die Variable initialisiert wurde oder nicht.

Dim s As String
If Now = #04/05/1973# Then
    s = "Hello World!"
End If

' BC42104.
If s IsNot Nothing Then
    s = s.ToLower()
End If

Einen weiteren Problemfall stellt das Auftreten der Compilerwarnung in jenem Szenario dar, in dem der Wert einer nicht explizit initialisierten Variablen einer anderen Variablen zugewiesen wird. Hierbei kann ebenfalls keine NullReferenceException auftreten, ja, die Zuweisung kann sogar semantisch korrekt sein, selbst wenn die Variable auf der rechten Seite der Zuweisung den Wert Nothing besitzt.

Dim s As String

' BC42104.
s = s

Weiterhin tritt die Compilerwarnung auf, wenn eine nicht explizit initialisierte Variable an eine Methode übergeben oder einer Eigenschaft zugewiesen wird. Dies ist deshalb problematisch, da einige Methoden durchaus mit übergebenen Verweisen auf Nothing zurecht kommen oder sogar derartige Verweise in bestimmten Situationen erwarten. Bestes Beispiel dafür ist die Funktion Len von Visual Basic, welche die Länge der übergebenen Zeichenfolge oder 0, wenn Nothing übergeben wurde, zurückgibt.

Dim s As String

' BC42104.
Foo(s)

' BC42104.
Me.Text = s

Lösungsansätze

Eine Verbesserung der Situation ist nur durch Ändern der Bedingungen, unter denen die Warnung auftritt, möglich. Das Auftreten der Warnung soll nicht zur Folge haben, daß Entwickler Variablen blindlings explizit auf Nothing initialisieren, obwohl dies ohnehin bereits implizit vom Compiler vorgenommen werden würde. Vielmehr soll das Auftreten des Compilerfehlers davon unabhängig sein ob die Variable explizit oder implizit auf Nothing initialisiert wurde. Die im Folgenden angeführten Bedingungen für bzw. gegen das Auftreten der Warnung wurden auf Basis der zuvor gezeigten Problemfälle entwickelt.

Die Compilerwarnung soll dann und nur dann auftreten, wenn

Dadurch wird verhindert, daß die Warnung auch in Fällen auftritt, in denen sie semantisch keinen Sinn ergibt. Ferner können so Situationen, in denen sicher eine NullReferenceException zur Laufzeit auftritt, vom Entwickler zur Codierungszeit gezielt entschärft werden.

Sie soll nicht auftreten, wenn eine nicht explizit initialisierte Variable

Im ersten der genannten Fälle und bei Zuweisen der Variable an eine Variable oder ein Arrayelement ist das Auftreten einer NullReferenceException ausgeschlossen. Bei der Übergabe der Variable in einem Methodenparameter oder bei der Zuweisung an eine Eigenschaft ist eine NullReferenceException zwar nicht ausgeschlossen, in vielen Fällen tritt jedoch keine derartige Ausnahme auf.

Schlußwort

In ihrer aktuellen Form ist die Compilerwarnung BC42104 nur von geringem Nutzen und in vielen Szenarien kontraproduktiv. Deshalb ist es ratsam, die Warnung zu deaktivieren. Dies kann bei Kompilieren mittels vbc.exe durch Angeben des Warnungscodes 42104 im Wert des Befehlszeilenparameters /nowarn (-nowarn) erfolgen. Wird zur Entwicklung Visual Studio 2005 eingesetzt, ist es erforderlich, die Projektdatei (Dateinamenserweiterung .vbproj) zu bearbeiten und den Warnungscode dem Element NoWarn hinzuzufügen. Es bleibt zu hoffen, daß sich Microsoft des Problems annimmt und die Warnung entsprechend den in diesem Artikel entwickelten Lösungsansätzen anpaßt oder ersetzt.