Behandlung ungültiger konstanter Angaben für Arraygrößen, -grenzen und -indizes in Visual Basic .NET und C#
Einleitung
Oft wird bei Diskussionen zwischen Benutzern der Programmiersprachen Visual Basic .NET und C# von Seiten der C#-Benutzer vorgebracht, daß in C# geschriebener Quellcode expliziter sei als in Visual Basic .NET mit aktiviertem Option Strict On
abgefaßter Code. Einer näheren Betrachtung hält diese Aussage jedoch nicht stand. Der vorliegende Artikel demonstriert am Beispiel der Behandlung ungültiger konstanter Angaben für Arraygrößen, -grenzen und -indizes mangelnde Explizitheit in der Programmiersprache C# und eine in diesem Zusammenhang auftretende unbedeutende Inkonsistenz im Verhalten des Compilers der Programmiersprache Visual Basic .NET.
Der besseren Lesbarkeit halber werden im Folgenden anstelle der sprachspezifischen Typpseudonyme Integer
/int
und Long
/long
die Typnamen System.Int32
und System.Int64
aus der Klassenbibliothek des .NET Framework verwendet.
Größen von Arraydimensionen in .NET
In .NET ist die Anzahl der Elemente in einem Array durch die größte im Typ native int
, also etwa int32
(System.Int32
), darstellbare Zahl begrenzt ([1], Teil III CIL Instruction Set, Kap. 4.19 newarr
– create a zero-based, one-dimensional array, S. 113). Die Programmiersprachen Visual Basic .NET und C# unterstützen Elementanzahlen des Typs Int32
je Dimension. Damit wird die Anzahl von Elementen einer Dimension durch den prozessorunabhängigen Wert von Int32.MaxValue
nach oben begrenzt. Der als Arraygröße, -grenze und -index angegebene Wert muß schlußendlich in Form des Typs Int32
vorliegen. Visual Basic .NET und C# unterscheiden sich darin, wie sichergestellt wird, daß konstante Angaben bei den jeweiligen Sprachelementen im gültigen Wertebereich zu liegen kommen.
Das Verhalten von Visual Basic .NET
In den Anweisungen Dim
und ReDim
sowie bei Arrayzugriffen übergebene Grenzen und Indizes müssen den Typ Int32
besitzen ([2], Kap. 9.6.3.3 Array-Size Initializers). Werden sie in Form eines anderen ganzzahligen Datentyps übergeben, ist eine Typumwandlung zu Int32
mittels CInt
oder CType
erforderlich; andernfalls tritt ein beim Versuch, den Code zu kompilieren, der Kompilierungsfehler BC30439 (Option Strict On
läßt keine impliziten Typumwandlungen von Long
in Integer
zu) auf. Betrachten wir dazu das im nachstehenden Listing angegebene Beispiel der Dim
-Anweisung.
Versucht man, eine negative Elementanzahl ungleich −1 (dieser Anzahl kann übergeben werden, um das Array zu leeren) des Typs Int32
zu übergeben, löst der Compiler den Fehler BC30611 (Arraydimensionen können keine negative Größe haben) aus. Lediglich im Fall der Übergabe des unzuläßigen Werts von Int32.MaxValue
wird zur Laufzeit eine Ausnahme des Typs System.OverflowException
(Die arithmetische Operation hat einen Überlauf verursacht) geworfen.
Das Verhalten von C#
Verglichen mit Visual Basic .NET stellt C# wesentlich geringere Anforderungen an konstante Angaben für Arraygrößen und -indizes. Die Spezifikation fordert lediglich, daß die übergebene Größe bzw. der Index implizit in den Typ Int32
umwandelbar ist ([3], Kap. 19.3 Array element access, S. 276). Falls eine Typumwandlung erforderlich wird, die Angabe also nicht den Typ Int32
besitzt, erfolgt diese zur Laufzeit. Nachstehendes Listing enthält zum im vorigen Listing angegebenen Visual-Basic-.NET-Code äquivalenten Code in C#.
Der oben angegebene Code läßt sich fehlerfrei kompilieren. Bei der Ausführung wird jedoch eine Ausnahme des Typs System.OverflowException
(Die arithmetische Operation hat einen Überlauf verursacht) geworfen, da 2.147.483.648 nicht im Datentyp Int32
dargestellt werden kann. Der Compiler erkennt ungültige konstante negative Angaben für Größen und Indizes und behandelt sie mit der Kompilierungswarnung (Stufe 2) CS0251 (Indizierung eines Arrays mit einem negativen Index (Arrayindizes starten immer mit Null)). Über die Compileroption /warnaserror
des Befehlszeilencompilers csc.exe
kann die Warnung wie ein Fehler gehandhabt werden; eine entsprechende Option besteht auch in den Projekteigenschaften von C#-Projekten innerhalb der Entwicklungsumgebung Visual Studio .NET.
Schlußwort
Wie anhand von Beispielen gezeigt wurde, unterscheiden sich Visual Basic .NET und C# bei der Handhabung konstanter Angaben für Arraygrößen, -grenzen und -indizes, sofern diese nicht den Typ Int32
besitzen. Visual Basic .NET prüft konstante Angaben bis auf einen Ausnahmefall zur Kompilierungszeit auf deren Gültigkeit und schöpft damit die Möglichkeiten eines Compilers in hohem Maße aus. Im Gegensatz dazu stellt C# Validierung dieser Angaben zur Kompilierungszeit in weit geringerem Umfang bereit. Während durch eine Anpassung des Compilers von Visual Basic .NET bestehender Code nur in geringem Ausmaß verändert werden müßte, würde eine Änderung im Verhalten des C#-Compilers umfangreichere Nachbearbeitungen des Codes erforderlich machen. Daher ist es unwahrscheinlich, daß das spezifizierte Verhalten des Compilers von C# in einer zukünftigen Version zu Gunsten einer umfassenderen Überprüfung des Quellcodes auf semantische Korrektheit zur Kompilierungszeit verändert wird.
Literaturverzeichnis
- [1]
- Microsoft Corporation: Standard ECMA-335 – Common Language Infrastructure (CLI), 2nd edition, ECMA, Dezember 2002.
- [2]
- Microsoft Corporation: Visual Basic Language Specification, Dokumentation zu Visual Basic .NET 2003, MSDN, 2003.
- [3]
- Microsoft Corporation: Standard ECMA-334 – C# Language Specification, 2nd edition, ECMA, Dezember 2002.