Mit Visual Basic 2010 gibt es es einige neue coole Sprachfeatures, mit denen Visual Basic – wie beispielsweise bei Expression-Lambdas ohne Rückgabewerte oder mehrzeiligen Statement-Lambdas – mit C# gleichzieht. Endlich, muss man sagen, denn das waren Features, die längst überfällig waren.
Bei einigen der neuen Features in Visual Basic 2010 übertrumpft es C# sogar in Sachen Komfort – Collection und Array Initializers gehören beispielsweise zu dieser Kategorie neuer Funktionen. Ein Beispiel:
Wollten Sie in einer der vorherigen Versionen mithilfe von Reflection Instanz einer Klasse erstellen, so konnte man sich bis Visual Basic 2008 des folgenden Codes bedienen:
Dim tk = GetType(Testklasse). _
GetConstructor(New Type() {}). _
Invoke(New Object() {})
Hier wird das Typ-Objekt der Klasse Testklasse ermittelt. GetConstructor ermittelt anschließend den Konstruktor mit der Signatur, der den Typen entspricht, die durch das Type-Array übergeben werden, und Invoke ruft schließlich den Konstruktor mit den entsprechenden Parametern auf. Die Übergabe eines leeren Arrays eínes bestimmten Typs erfolgt also auf die bis dato einzig mögliche Weise: New ArrayType() { }.
In C# sieht das ganz ähnlich aus, und zwar bis heute, bis zur Visual C# 2010-Version:
var f = typeof(Testklasse).
GetConstructor(new Type[0]).
Invoke(new Object[] { });
Anders als in VB können in C#, dadurch dass bei Array-Definitionen die Anzahl der Elemente und nicht die obere Array-Grenze angegebene wird, leere aber definierte Arrays auf zwei Weisen bestimmt werden: Einmal durch die Angabe des Typs und 0 in eckigen Klammern oder durch die Übergabe des Typs und einer Leerklammer zum Zeichen dafür, dass es sich um ein Array handelt, sowie einer leeren Liste als Objekt-Initialisierer mit zwei geschweiften Klammern.
Ab Visual Basic 2010 geht das noch einfacher:
Dim tk = GetType(Testklasse).
GetConstructor({}).
Invoke({})
Der Visual Basic-Compiler macht an dieser Stelle etwas ziemlich bemerkenswertes: Die GetConstructor-Methode definiert durch ihre Signatur, welchen Typ Argument sie erwartet, und leitet den zwar leeren aber vorhandenen Array Initializer aus dem Kontext in den richtigen Typen ab – in diesem Fall in ein Array vom Typ Type. Und das gleiche passiert anschließend bei der Invoke-Methode, für die aus dem Array-Initializer-Literal abermals der korrekte Typ abgeleitet wird, nämlich ein leeres Array vom Typ Object.
Übrigens, in diesem Zusammenhang ist es nochmals wichtig zu wissen, das ein Array eigentlich drei und nicht nur, wie andere Referenztypen, zwei Definitionszustände haben können. Zum einen kann eine Objektvariable vom Typ Array deklariert sein, aber auf keine Speicheradresse zeigen, also eigentlich den Wert Nothing haben:
Private myByteArray As Byte()
Zum anderen kann man das gleiche Byte-Array auch mit 0-Elementen definieren, und das würde folgender Maßen funktionieren:
Private myByteArray As Byte() = New Byte() {}
Der Unterschied hier ist: myByteArray zeigt nun auf den Speicherbereich im Managed Heap, der die Elemente beinhaltet; auch wenn es gar keine Elemente gibt. Das Array ist jetzt nicht mehr Nothing, auch wenn seine Length-Eigenschaft den Wert 0 zurückliefern würde.
Und schließlich können wir bei der Deklaration auch noch eine Reihe von Schreibformen verwenden, um Arrays mit einer Reihen von Elementen zu definieren:
'Byte-Array mit 11-Elementen (0-10)
Private myByteArray1(10) As Byte
'Integer-Array mit 10-Elementen (0-9), mit Werten vorbelegt
Private myIntegerArray() As Integer = New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
'Double-Array mit 10-Elementen (0-9), mit Werten vorbelegt
Private myDoubleArray() As Double = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
'String-Array mit 5 Elementen (nur auf Prozedur-Ebene definierbar).
Dim myStringArray = {"Andreas", "Ramona", "Klaus", "Adriana", "Magges"}
Die letzte “Version” arbeitet mit lokalem Typrückschluss für Array Initializers; lokaler Typrückschluss funktioniert aber nur auf Prozedur-Ebene – Feldvariablen einer Klasse lassen sich auf diese Weise also nicht definieren.
WICHTIG: Entgegen vorherrschender Meinung lassen sich Arrays in VB übrigens sehr wohl ohne die Hilfe von ReDim dynamisch neu definieren. Und zwar funktioniert das auf die folgende Weise:
'Ab jetzt Speicherplatz für 21 Elemente reservieren, entweder mit ReDim
ReDim myDoubleArray(20)
'oder auf diese Art und Weise. Hier wird in runden Klammern die Array-Obergrenzen angegeben.
myDoubleArray = New Double(20) {}