Visual Basic ermöglicht die Konvertierung vieler Datentypen in andere Datentypen – dabei bleibt allerdings die starke Typisierung auf der Strecke. In der Zusammenarbeit mit Entwicklern im Projekt, oder bei Trainings habe ich immer wieder festgestellt, dass dieses “tolle” Feature, eher hinderlich als nützlich ist, da es negative Auswirkungen auf die Code-Qualität haben kann.
Option Strict ist standardmäßig nicht aktiv – also Off. Die Option kann für einzelne Dateien (sogar innerhalb partieller Klassen), auf Projektebene oder als Voreinstellung in Visual Studio aktiviert werden. Option Strict Off lockert die starke Typisierung. Ich behaupte jetzt einfach mal, dass es kein Szenario gibt, das den Verzicht auf starke Typisierung erforderlich macht.
Ich empfehle immer, die Option in den Standardprojekteinstellungen zu aktivieren – so muss man die Projekteinstellungen nicht einzeln nach Anlegen neuer Projekte setzen bzw. kann dies nicht vergessen. Beachten Sie, das diese Einstellung keine Auswirkung auf bereits bestehende VB-Projekte hat; diese können Sie über die Projekteigenschaften anpassen.
Welche Auswirklung der Verzicht starker Typisierung haben kann, zeigt das folgende Beispiel; betrachten Sie doch einmal den folgenden Dreizeiler.
Dim x Dim y = Int64.MaxValue x = y
Der Code lässt sich problemlos übersetzen und macht auch zur Laufzeit keine Probleme. Im folgenden Beispiel habe ich den Code leicht modifiziert – ich habe für die Variable x den Typ Integer festgelegt.
Dim x As Integer = 0 Dim y = Int64.MaxValue x = y
Der Code kann noch immer ohne Fehlermeldung übersetzt werden – die Zuweisung von y an x wird aber zur Laufzeit mit einer OverflowException quitiert. Naja, möglicherweise finden Sie mein Beispiel etwas zu konstruiert – niemand würde solchen Code schreiben. Also habe ich das Beispiel noch einmal etwas verändert.
Function GetValue() Return Int64.MaxValue End Function Sub Main() Dim x As Integer = GetValue() End Sub
Ich denke Sie können sich leicht vorstellen, dass sich die Implementierung der GetValue()-Methode in einer anderen Quellcodedatei, oder sich auch einem anderen Assembly befindet – und der Fehler somit unentdeckt bleibt. Es könnte sein, dass die GetValue()-Methode in einer früheren Implementierung immer einen Int32-Wert lieferte und erst im späteren Projektverlauf auf Int64 geändert wurde.
Denkbar könnte es aber auch sein, dass der Rückgabewert der GetValue()-Methode aus einer Berechnung hervorgeht, und dieser nur in seltenen Fällen über den durch Int32 darstellbaren Bereich hinausgeht, sodass der Fehler nur sporadisch auftritt.
Wieso kann „mangelhafter“ Code erfolgreich übersetzt werden? Vor dem Übersetzen wird der Code verändert – das können Sie mit dem Reflector leicht nachprüfen. Dann sieht der Beispielcode plötzlich so aus…
Function GetValue() As Object Return &H7FFFFFFFFFFFFFFF End Function Public Sub Main() Dim x As Integer = Conversions.ToInteger(GetValue) End Sub
Der Compiler erzeugt Code, der stark typisiert ist. Wie aber bereits festgestellt, wird zur Laufzeit ein Fehler ausgelöst. Mittels Option Strict On kann dieses Problem weitestgehend vermieden werden. Dann ist es zum einen unmöglich Methoden und Eigenschaften ohne Angabe eines Rückgabetyps zu deklarieren, bzw. die Rückgabe an eine Variable eines abweichenden Typs zuzuweisen – und Sie stellen sicher, das der Code so übersetzt wird, wie Sie ihn formuliert haben.
Natürlich hätten Sie den Code genau so schreiben können, wie er durch den Compiler bei nicht gesetzter Option Strict Option erzeugt würde –es wird deutlich das starke Typisierung nicht automatisch auch zu korrektem Code führt – dafür müssen Sie nach wie vor selbst sorgen.
Die korrigierte GetValue()-Methode sieht dann so aus…
Function GetValue() As Int64 Return Int64.MaxValue End Function
Der Entwickler, der die GetValue()-Methode verwendet, würde vom Compiler aufmerksam gemacht werden, wenn der Typ der Variablen x nicht kompatibel zum Rückgabetyp ist. Folgender Aufruf ist dann nicht mehr möglich…
Public Sub Main() Dim x As Integer = GetValue() End Sub
Dieser muss angepasst werden…
Public Sub Main() Dim x As Int64 = GetValue() End Sub
Die Verwendung von Option Strict ist absolut sinnvoll. Setzen Sie die Option immer ein – egal wie erfahren Sie im Umgang mit VB .NET sind. So ist man stets dazu angehalten, sich über passende Typen Gedanken zu machen und kann Seiteneffekte bereits im Vorfeld vermeiden.
Zum Abschluss zeige ich noch ein paar kurze Beispiele, was im Code mit Option Strict Off unter Visual Basic .NET möglich ist und was der Compiler tatsächlich daraus macht. Ich möchte mit den Beispielen ein paar Möglichkeiten aufzeigen, wie Sie Ihren Code sicherer machen können, wenn Sie beispielsweise Option Strict auf Grund eines LateBinding- Szenarios nicht einsetzen wollen.
For Each Apfel In Birnen
Dim list = GetListObject() For Each item In list Next
Sowas gibt es wirklich – und das kommt dabei heraus…
Dim VB$t_ref$L0 As IEnumerator Dim list As Object = RuntimeHelpers.GetObjectValue(GetListObject) Try VB$t_ref$L0 = DirectCast(list, IEnumerable).GetEnumerator Do While VB$t_ref$L0.MoveNext Dim item As Object = RuntimeHelpers.GetObjectValue(VB$t_ref$L0.Current) Loop Finally If TypeOf VB$t_ref$L0 Is IDisposable Then TryCast(VB$t_ref$L0,IDisposable).Dispose End If End Try
Sollte GetListObject kein Objekt liefern, dessen Typ IEnumerable implementiert, äußert sich dies in einer InvalidCastException. Der folgende Code ist besser geeignet…
Dim list As IEnumerable = TryCast(GetListObject(), IEnumerable) If Not (list Is Nothing) Then For Each item As Object in list Next End If
Noch ein Tipp: Code-Generierung via CodeDOM
Wenn Sie Option Strict bei der Code-Generierung explizit setzen möchten, können Sie dies über über die UserData-Eigenschaft der CodeCompileUnit erreichen.
...
Dim compileUnit As New CodeCompileUnit()
compileUnit.UserData.Add("AllowLateBound", False)
...


