Option Strict Off = Option Shit On
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)
...
Links
Umstieg von VB 6.0 auf Visual Basic .NET: Option Explicit und Option Strict per Vorlage
http://msdn.microsoft.com/de-de/library/bb979488.aspx
[...] Option Strict Off [...] "Bitte gehen Sie mit dieser Möglichkeit aber
äußerst sparsam um - noch besser: Vergessen Sie, was Sie darüber gerade gelesen haben." [...]
Coding Horror: Option Strict and Option Explicit in VB.NET 2005
http://www.codinghorror.com/blog/archives/000355.html