Seit der Geburt der Visual Basic-Sprache im Jahr 1991 ist sie ein äußerst effizientes Werkzeug zum Erstellen von Anwendungen. Fast 20 Jahre später bietet es weiterhin eine einfache Integration in das Microsoft .NET Framework und ermöglicht Entwicklern das Schreiben von Anwendungen, die sich über Desktops, Telefone, Browser und sogar die Cloud erstrecken.
Microsoft wird diesen Monat Visual Studio 2010 veröffentlichen, das Visual Basic Version 10 (manchmal auch VB 2010 oder VB10 genannt) enthält. Diese Version ist die bisher leistungsstärkste und enthält viele zeitsparende Funktionen, die Entwicklern helfen, mit weniger Codezeilen mehr zu erreichen. Hier erhalten Sie alle notwendigen Inhalte, um Visual Basic in Visual Studio 2010 vollständig zu verstehen und zu nutzen.
Koevolution
In der Vergangenheit wurden Visual Basic und C# von getrennten Teams entwickelt, was oft dazu führte, dass Funktionen zuerst in einer Sprache und dann in der anderen erschienen. Beispielsweise verfügt C# über automatisch implementierte Eigenschaften und Auflistungsinitialisierer, die in Visual Basic nicht zu finden sind, und Visual Basic verfügt über Funktionen wie späte Bindung und optionale Parameter, die in C# nicht zu finden sind. Aber jedes Mal, wenn eine Sprache eine neue Funktion erhält, verlangen viele Kunden, dass diese Funktion auch in der anderen Sprache hinzugefügt wird.
Um diesem Bedarf gerecht zu werden, hat Microsoft die Visual Basic- und C#-Teams zusammengelegt, um eine Co-Evolution-Strategie zu implementieren. Ziel ist es, die gemeinsame Entwicklung dieser Sprachen zu fördern. Wenn eine Hauptfunktion in einer Sprache eingeführt wird, erscheint sie auch in der anderen Sprache. Das heißt nicht, dass jede Funktion in beiden Sprachen vorhanden ist und auf die gleiche Weise funktioniert. Tatsächlich hat jede Sprache ihre eigene Geschichte, Seele und Ausstrahlung – und es ist wichtig, diese Eigenschaften zu bewahren.
In .NET Framework 4 machten Visual Basic und C# einen großen Schritt in Richtung dieses Ziels, indem sie jeweils viele der vorhandenen Funktionen des anderen übernahmen. Die Koevolution betrifft jedoch nicht nur die bisherige Funktionalität; sie ist auch eine Strategie für die zukünftige Entwicklung dieser Sprachen. In diesem Sinne führt .NET Framework 4 leistungsstarke neue Funktionen in beiden Sprachen ein, wie z. B. die dynamische Sprachlaufzeit, eingebettete Interop-Typen und generische Varianz, sodass Visual Basic- und C#-Entwickler die Vorteile von .NET Framework voll ausschöpfen können.
Was ist neu in Visual Basic 2010?
Neue Funktionen in Visual Basic 2010 sollen Ihnen dabei helfen, mit weniger Codezeilen mehr zu erreichen. Unser Visual Basic-Designteam hat sich die Stellen genau angesehen, an denen Entwickler normalerweise viel mühsamen Boilerplate-Code schreiben müssen, und Wege gefunden, die Arbeit stattdessen dem Compiler überlassen zu können. Dies ist natürlich eine Gesamtansicht. Schauen wir uns nun die einzelnen Funktionen genauer an.
Implizites Zeilenfortsetzungszeichen
Visual Basic ist eine zeilenorientierte Sprache, die zur Verbesserung der Lesbarkeit eine klare Syntax ähnlich der englischen verwendet. Dies führt jedoch häufig dazu, dass der Code die Grenze von 80 Zeichen pro Zeile erreicht, was Entwickler dazu zwingt, viel zu scrollen. Sie können den Unterstrich verwenden, um dem Compiler mitzuteilen, dass die Verarbeitung der nächsten Zeile als aktuelle Zeile fortgesetzt werden soll (d. h. mehrere physische Zeilen werden als eine einzige logische Zeile behandelt). Aber das wiederholte Eintippen des Unterstrichs war schon immer lästig, und tatsächlich war es jahrelang eine der wichtigsten Funktionsanfragen, dieses Problem durch den Compiler beheben zu lassen.
In Visual Basic 2010 kann der Compiler dieses Problem lösen. Der Compiler weiß nun, welche Token (z. B. Kommas, Klammern und Operatoren) normalerweise vor Zeilenfortsetzungszeichen erscheinen, und fügt Zeichen ein, sodass Entwickler keine Zeichen mehr einfügen müssen. Beispielsweise ist es sicherlich nicht logisch, eine Visual Basic-Anweisung mit einem Komma zu beenden. Der Compiler weiß dies. Wenn der Compiler also einen Stream von Tokens wie {comma, enter} sieht, schließt er auf das Vorhandensein eines Zeilenfortsetzungszeichens. wie in Abbildung gezeigt. Das Beispiel in 1 wird gezeigt.
Abbildung 1 Zeilenfortsetzungszeichen ableiten
<Extension()>
Funktion FilterByCountry(
ByVal customer As IEnumerable(Of Customer),
ByVal (Land als String) als IEnumerable(Of Customer)
Dim query=
Von c In Kunden
Wobei c.Country = Land
Wählen Sie <Kunde>
<%=
c.Name &
, &
c.Land
%>
</Kunde>
Rückfrage
Funktion beenden
In Visual Basic 2008 würde der Code in Abbildung 1 9 Unterstriche erfordern. In jedem der folgenden Fälle leitet der Compiler jedoch ab, wann der Unterstrich erforderlich ist, und lässt zu, dass er ignoriert wird:
Nach dem Attribut <Extension()>
nach ((linke Klammer) in der Methodendeklaration
nach dem , (Komma) des ersten Parameters
vor ) (rechte Klammer) in der Methodendeklaration
after = (Gleichheitszeichen)
nach <%= (dem öffnenden Tag eines eingebetteten Ausdrucks)
Nach jedem kaufmännischen Und (kaufmännisches Und) im XML-Text
vor %> (Endtag des eingebetteten Ausdrucks)
Diese neue Compilerfunktion ist besonders nützlich für Methodensignaturen, die im gezeigten Beispiel auch bei mehr als 80 Zeichen einwandfrei funktionieren (wenn sich jeder Teil in derselben Zeile befindet). In Abbildung 2 sehen Sie alle Kombinationen von Tags und Positionen, für die Zeilenfortsetzungszeichen implizit sind.
Abbildung 2 Wenn das Zeilenfortsetzungszeichen implizit ist
markieren | Vor | nach |
, (Komma), . (Punkt), > (Attribut), ( { (linke Klammer), <%= (Start-Tag des eingebetteten Ausdrucks (XML-Text)) | X | |
), }, ] (rechte Klammer), %> (End-Tag des eingebetteten Ausdrucks) | X | |
Alle LINQ-Schlüsselwörter: Aggregieren, Unterscheiden, Von, Gruppieren nach, Gruppenverknüpfen, Verbinden, Lassen, Sortieren nach, Auswählen, Überspringen, Während überspringen, Nehmen, Während nehmen, Wo, In, In, Auf, Aufsteigend, Absteigend | X | X |
Operator: +, -,*,/,/,^,>>,<<,Mod,&,+=,-=,*=,/=,/=,^=,>>=,<<=, & =, <, <=, >, >=, <>, Is, IsNot, Like, And, Or, Xor, AndAlso, OrElse | X | |
With (im Objektinitialisierer) | X |
Wie Sie sehen, gibt es in der Sprache über 60 Stellen, an denen der Unterstrich nicht erforderlich ist. (Tatsächlich erfordert keines der Codebeispiele in diesem Artikel Zeilenfortsetzungszeichen.) Natürlich können Sie weiterhin den Unterstrich verwenden, sodass Code aus früheren Versionen von Visual Basic weiterhin wie erwartet kompiliert wird.
StatementLambda
Der Begriff Lambda mag zunächst beängstigend klingen, aber ein Lambda ist nur eine Funktion, die innerhalb einer anderen Funktion definiert ist. Visual Basic 2008 führte Lambda-Ausdrücke mit dem Schlüsselwort Function ein:
Dim customers As Customer() = ...
Array.FindAll(customers, Function(c) c.Country = Kanada)
Mit Lambda-Ausdrücken können Sie Logik lokal auf granulare und kompakte Weise ausdrücken, ohne sie auf mehrere Methoden aufteilen zu müssen. Hier ist zum Beispiel die Darstellung des vorherigen Codes in Visual Basic 2005 (das keine Lambda-Ausdrücke unterstützt):
Dim query = Array.FindAll(customers, AddressOf Filter)
...
Funktion Filter(ByVal c As customer) As Boolean
Geben Sie c.Country = Kanada zurück
Funktion beenden
Leider erfordern die Lambda-Ausdrücke von Visual Basic 2008, dass der Ausdruck einen Wert zurückgibt, daher der folgende Code:
Array.ForEach(customers, Function(c) Console.WriteLine(c.Country))
Wird zu folgender Situation führen:
'Compile error: Expression does not produce a value.
Console.WriteLine ist eine Sub-Prozedur (in C# ungültig), daher gibt sie keinen Wert zurück, weshalb der Compiler einen Fehler generiert. Um mit dieser Situation umzugehen, hat Visual Basic 2010 die Unterstützung für Anweisungs-Lambdas eingeführt, bei denen es sich um Lambdas handelt, die eine oder mehrere Anweisungen enthalten:
Array.ForEach(customers, Sub(c) Console.WriteLine(c.Country))
Da Console.WriteLine keinen Wert zurückgibt, können wir einfach ein Sub-Lambda anstelle eines Funktions-Lambda erstellen. Hier ist ein weiteres Beispiel mit mehreren Anweisungen:
Array.ForEach(customers, Sub(c)
Console.WriteLine(Ländername:)
Console.WriteLine(c.Country)
Ende Sub)
Wenn dieser Code ausgeführt wird, werden für jeden Kunden zwei Zeilen gedruckt. Beachten Sie außerdem, dass, wenn Sie beim Codieren mit der Maus über c fahren, Sie sehen werden, dass der Compiler den Typ als Kunde ableitet (es ist auch zulässig, c als Kunde einzugeben, um den Typ explizit zu deklarieren). Das dynamische Schreiben von Ereignishandlern ist eine weitere großartige Verwendung von Anweisungslambdas:
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
MsgBox(Schaltfläche angeklickt)
'Fügen Sie hier eine komplexere Logik ein
Sub beenden
Und tatsächlich können Sie Anweisungs-Lambdas mit einer in Visual Basic 2008 eingeführten Funktion verwenden: der losen Delegierung. (Sie können Delegaten – typsichere Funktionszeiger – verwenden, um mehrere Funktionen gleichzeitig auszuführen.) Diese Kombination führt zu einer viel einfacheren Signatur:
AddHandler b.Click, Sub()
MsgBox(Schaltfläche angeklickt)
'Fügen Sie hier eine komplexere Logik ein
Sub beenden
Durch die Lockerheit von Delegaten können Sie Parameter in Event-Handlern vollständig ignorieren – das ist ein großer Vorteil, solange sie überhaupt nicht verwendet werden und somit nur optisch aufdringlich sind.
Zusätzlich zu den einzeiligen Sub-Lambdas und mehrzeiligen Sub-Lambdas, die wir bisher gesehen haben, unterstützt Visual Basic 2010 auch mehrzeilige Funktions-Lambdas:
Dim query = customers.Where(Function(c)
„Nur Kunden zurückgeben, die nicht gespeichert wurden.“
'Fügen Sie hier eine komplexere Logik ein
Geben Sie c.ID = -1 zurück
Endfunktion)
Ein weiterer interessanter Aspekt von Anweisungslambdas ist, wie sie sich mit den in Visual Basic 2008 eingeführten anonymen Delegaten überschneiden. Diese Delegaten werden oft mit den anonymen Methoden von C# verwechselt, obwohl sie nicht unbedingt identisch sind. Eine anonyme Delegierung erfolgt, wenn der Visual Basic-Compiler den Delegatentyp basierend auf der Methodensignatur des Lambda ableitet:
Dim method = Function(product As String)
Wenn Produkt = Papier, dann
Geben Sie 4,5-Zoll-Einheiten auf Lager zurück
Anders
Geben Sie 10 '10 von allem anderen zurück
Ende wenn
Funktion beenden
MsgBox(Methode(Papier))
Wenn Sie diesen Code ausführen, wird im Meldungsfeld der Wert 4,5 angezeigt. Wenn Sie außerdem mit der Maus über die Methode fahren, wird der Text Dim method As <Function(String) As Double> angezeigt. Da wir keinen tatsächlichen Delegatentyp bereitgestellt haben, generiert der Compiler automatisch einen wie folgt:
Delegate Function $compilerGeneratedName$(product As String) As Double
Dies wird als anonymer Delegat bezeichnet, da er nur im vom Compiler generierten Code und nicht im geschriebenen Code erscheint. Beachten Sie, dass der Compiler den Rückgabetyp auf Double ableitet, wenn tatsächlich keine As-Klausel zur Angabe des Rückgabetyps des Lambda bereitgestellt wird. Der Compiler prüft alle Rückgabeanweisungen innerhalb des Lambda und ermittelt die Typen Double (4.5) und Integer (10):
'Notice the As Single
Dim-Methode = Function(product As String) As Single
Wenn Produkt = Papier, dann
Geben Sie 4,5-Zoll-Einheiten auf Lager zurück
Anders
Geben Sie 10 '10 von allem anderen zurück
Ende wenn
Funktion beenden
Anschließend führt es seinen Basisalgorithmus aus und stellt fest, dass es 10 sicher in einen Double-Wert konvertieren kann, 4,5 jedoch nicht sicher in einen Integer-Wert konvertieren kann. Daher ist Double die bessere Wahl.
Sie können den Rückgabetyp auch explizit steuern. In diesem Fall versucht der Compiler nicht, den Typ abzuleiten. Es ist sehr üblich, das Lambda einer Variablen mit einem expliziten Delegate-Typ zuzuweisen, anstatt sich darauf zu verlassen, dass der Compiler den Delegate-Typ ableitet:
Dim method As Func(Of String, Single) =
Funktion(Produkt)
Wenn Produkt = Papier, dann
Geben Sie 4,5-Zoll-Einheiten auf Lager zurück
Anders
Geben Sie 10 '10 von allem anderen zurück
Ende wenn
Funktion beenden
Da ein expliziter Zieltyp bereitgestellt wird, ist es nicht erforderlich, „As String“ oder „As Single“ zu deklarieren; der Compiler kann auf der Grundlage des Delegattyps auf der linken Seite der Anweisung auf dessen Existenz schließen. Wenn Sie also mit der Maus über das Produkt fahren, sehen Sie, dass der abgeleitete Typ String ist. Sie müssen nicht mehr „Als Single“ angeben, da der Delegate-Typ diese Informationen bereits bereitstellt. Im vorherigen Beispiel sieht die Signatur des Func-Delegaten (der im .NET Framework enthalten ist) wie folgt aus:
Delegate Function Func(Of T, R)(ByVal param As T) As R
Es gibt eine kleine Ausnahme, wie wir später im Abschnitt über generische Varianz sehen werden.
Automatisch implementierte Eigenschaften
In Visual Basic sind Eigenschaften Klassenmitglieder, die den Zustand eines Objekts der Außenwelt zugänglich machen. Eine typische Eigenschaftsdeklaration sieht wie folgt aus:
Private _Country As String
Eigenschaftsland als Zeichenfolge
Erhalten
Return_Country
Beenden Sie Get
Set(ByVal-Wert als String)
_Land = Wert
Endsatz
End-Eigenschaft
Ein eigentlich sehr einfaches Konzept mit 10 Zeilen Code. Da ein typisches Objekt oft Dutzende von Eigenschaften hat, fügen Sie Ihrer Klassendefinition am Ende eine Menge Standardcode hinzu. Um solche Aufgaben zu vereinfachen, führt Visual Basic 2010 automatisch implementierte Eigenschaften ein, mit denen Sie einfache Eigenschaften mit nur einer Codezeile definieren können:
Property Country As String
In diesem Fall wird der Compiler weiter ausgeführt und generiert automatisch Getter, Setter und unterstützende Felder. Der Name eines unterstützten Felds ist immer der Name eines Attributs, dem ein Unterstrich vorangestellt ist: in diesem Beispiel _Country. Diese Namenskonvention stellt die Kompatibilität der binären Serialisierung sicher, wenn automatisch implementierte Eigenschaften in reguläre Eigenschaften geändert werden. Die binäre Serialisierung funktioniert weiterhin, solange die Namen der Hintergrundfelder identisch sind.
Eines der netten Dinge, die Sie mit automatisch implementierten Eigenschaften tun können, ist die Angabe eines Initialisierers, der den Standardwert der Eigenschaft festlegt, wenn der Konstruktor ausgeführt wird. Beispielsweise setzt ein häufiges Szenario mit Entitätsklassen den Primärschlüssel auf einen Wert wie -1, um anzuzeigen, dass er sich in einem nicht gespeicherten Zustand befindet. Der Code sieht folgendermaßen aus:
Property ID As Integer = -1
Wenn der Konstruktor ausgeführt wird, wird das Hintergrundfeld (_ID) automatisch auf den Wert -1 gesetzt. Die Initialisierungssyntax funktioniert auch für Referenztypen:
Property OrderList As List(Of Order) = New List(Of Order)
Da Sie den Namen des Typs nicht zweimal eingeben müssen, weist die vorherige Codezeile möglicherweise keine sehr offensichtlichen Visual Basic-Merkmale auf. Die gute Nachricht ist, dass es eine kürzere Syntax für reguläre Variablendeklarationen gibt, die mit der von Visual Basic erlaubten Syntax übereinstimmt:
Property OrderList As New List(Of Order)
Sie können diese Syntax sogar mit einem Objektinitialisierer verwenden, um das Festlegen anderer Eigenschaften zu ermöglichen:
Property OrderList As New List(Of Order) With {.Capacity = 100}
Für komplexere Eigenschaften ist natürlich weiterhin eine erweiterte Syntax erforderlich. Sie können weiterhin Property{Tab} eingeben, um das alte Eigenschaftsfragment zu aktivieren. Alternativ können Sie nach Eingabe der ersten Zeile der Eigenschaft einfach Get{Enter} eingeben und die IDE generiert die Eigenschaft im alten Stil:
Property Name As String
Erhalten
Beenden Sie Get
Set(ByVal-Wert als String)
Endsatz
End-Eigenschaft
Üblicherweise ist die neue Eigenschaftssyntax fast identisch mit der von öffentlichen Feldern, warum also nicht stattdessen öffentliche Felder verwenden? Dafür gibt es mehrere Gründe:
Der Großteil der .NET-Datenbindungsinfrastruktur basiert auf Eigenschaften und nicht auf Feldern.
Eine Schnittstelle kann nicht das Vorhandensein eines Feldes erzwingen; sie kann das Vorhandensein eines Attributs erzwingen.
Eigenschaften bieten längerfristige Flexibilität für sich ändernde Geschäftsregeln. Angenommen, jemand führt eine Regel ein, die besagt, dass Telefonnummern 10 Ziffern lang sein müssen. Diese Validierung kann nicht durchgeführt werden, wenn sie einem öffentlichen Feld zugewiesen ist. Die Umwandlung öffentlicher Felder in Eigenschaften ist eine bahnbrechende Änderung für Szenarien wie binäre Serialisierung und Reflektion.
Sammlungsinitialisierer
Eine gängige .NET-Praxis besteht darin, eine Sammlung zu instanziieren und die Sammlung dann zu füllen, indem die Add-Methode einmal für jedes Element aufgerufen wird:
Dim digits As New List(Of Integer)
Ziffern.Add(0)
Ziffern.Add(1)
Ziffern.Add(2)
Ziffern.Add(3)
Ziffern.Add(4)
Ziffern.Add(5)
Ziffern.Add(6)
Ziffern.Add(7)
Ziffern.Add(8)
Ziffern.Add(9)
Aber für ein grundsätzlich einfaches Konzept gibt es einen großen syntaktischen Aufwand. Visual Basic 2010 hat Sammlungsinitialisierer eingeführt, um Ihnen das Instanziieren von Sammlungen zu erleichtern. Für diesen Code:
Dim digits = New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Der Compiler generiert automatisch alle Aufrufe der Add-Methode. Sie können auch die Syntaxfunktion „As New“ von Visual Basic verwenden:
Dim digits As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Beachten Sie, dass wir im Visual Basic-Team immer die Verwendung der zweiten Syntax (As New) anstelle der ersteren empfehlen, da der Code dadurch widerstandsfähiger gegenüber Änderungen in der Einstellung „Option Infer“ wird.
Sie können einen Sammlungsinitialisierer für jeden Typ verwenden, der die folgenden Anforderungen erfüllt:
Sie können den Typ mithilfe einer For Each-Anweisung durchlaufen – das heißt, der Typ implementiert IEnumerable. (Eine genauere/detailliertere Definition von Sammlungstypen finden Sie in Abschnitt 10.9.3 der Visual Basic-Sprachspezifikation unter msdn.microsoft.com/library/aa711986(VS.71).aspx).
Der Typ verfügt über einen zugänglichen (aber nicht unbedingt öffentlichen) parameterlosen Konstruktor.
Der Typ verfügt über eine zugängliche (aber nicht unbedingt öffentliche) Instanz oder Erweiterungsmethode namens Add.
Dies bedeutet, dass Sie Sammlungsinitialisierer auch für komplexere Typen wie Wörterbücher verwenden können:
Dim lookupTable As New Dictionary(Of Integer, String) From
{{1, Eins},
{2, Zwei},
{3, Drei},
{4, Vier}}
(Beachten Sie, dass diese Anweisung zwar fünf Zeilen umfasst, aber keine Unterstriche enthält.) In diesem Fall generiert der Compiler Code, der der alten Methode zum Initialisieren eines Wörterbuchs entspricht:
Dim lookupTable As New Dictionary(Of Integer, String)
lookupTable.Add(1, One)
lookupTable.Add(2, Two)
lookupTable.Add(3, Three)
lookupTable.Add(4, Four)
Der Compiler ruft die Add-Methode mit zwei Parametern statt einem auf. Dies ist möglich, da der an den Sammlungsinitialisierer übergebene Wert in verschachtelten Klammern steht, etwa so: {{1, Eins}, {2, Zwei}, …}. Für jeden Satz verschachtelter Klammern versucht der Compiler, diese Parameter an eine kompatible Add-Methode zu übergeben.
Es ist auch möglich, mithilfe von Erweiterungsmethoden Ihre eigene benutzerdefinierte Add-Implementierung bereitzustellen:
<Extension()>
Sub Add(ByVal source As IList(Of Customer),
ByVal id As Integer,
ByVal-Name als String,
ByVal (Stadt als String)
source.Add(Neuer Kunde mit
{
.ID = id,
.Name = Name,
.Stadt = Stadt
})
Sub beenden
(Sehen Sie sich all die fehlenden Unterstriche an!) Diese Methode erweitert jeden Typ, der IList(Of Customer) implementiert, was Ihnen dann die Verwendung der neuen Sammlungsinitialisierer-Syntax wie folgt ermöglicht:
Dim list = New List(Of Customer) From
{
{1, Jon, Redmond},
{2, Bob, Seattle},
{3, Sally, Toronto}
}
(Fügen Sie drei Kunden zur Liste hinzu). Sie können auch Sammlungsinitialisierer mit automatisch implementierten Eigenschaften verwenden:
Property States As New List(Of String) From {AL, AK, AR, AZ, ...}
Array-Literal
Neben leistungsfähigeren Möglichkeiten zum Arbeiten mit Sammlungstypen bietet Visual Basic 2010 auch einige leistungsstarke Verbesserungen für das Arbeiten mit Arrays. Gehen Sie von folgendem Code aus (funktioniert in älteren Versionen einwandfrei):
Dim numbers As Integer() = New Integer() {1, 2, 3, 4, 5}
Wenn man sich die Elemente in diesem Array ansieht, wird deutlich, dass es sich bei jedem Element um eine Ganzzahl handelt. Wenn man also die Ganzzahl tatsächlich zweimal in dieser Zeile ausgeben muss, bringt das keinen wirklichen Mehrwert. Mit Array-Literalen können Sie ein Array erstellen, indem Sie alle Elemente eines Arrays in geschweifte Klammern setzen und den Compiler die Typen automatisch ableiten lassen:
Dim numbers = {1, 2, 3, 4, 5}
Der Typ der Zahlen ist nicht Object, sondern Integer() (sofern Option Infer aktiviert ist). Der Grund dafür ist, dass das Array-Literal sich jetzt selbst darstellt und einen eigenen Typ hat. Nehmen wir ein komplexeres Beispiel:
Dim numbers = {1, 2, 3, 4, 5.555}
In diesem Fall wird der Zahlentyp als Double() abgeleitet. Der Compiler bestimmt den Typ, indem er jedes Element im Array untersucht und den Basistyp berechnet. Dabei verwendet er denselben Algorithmus, der zuvor zum Ableiten des Rückgabetyps eines Anweisungs-Lambda erläutert wurde. Was passiert, wenn kein Basistyp vorhanden ist? Zum Beispiel wie im folgenden Code gezeigt:
Dim numbers = {1, 2, 3, 4, 5}
In diesem Fall wird durch die Konvertierung einer Ganzzahl in einen String der Konvertierungsbereich verringert (d. h. es kann zur Laufzeit zu Datenverlust kommen), und in ähnlicher Weise wird durch die Konvertierung eines Strings in eine Ganzzahl auch der Konvertierungsbereich verringert. Der einzige sichere Typ zur Auswahl ist Object() (der Compiler generiert einen Fehler, wenn Option Strict aktiviert ist).
Array-Literale können verschachtelt werden, um mehrdimensionale Arrays oder gezackte Arrays zu bilden:
'2-dimensional array
Dim-Matrix = {{1, 0}, {0, 1}}
'gezacktes Array – die Klammern erzwingen zuerst die Auswertung des inneren Arrays
Dim gezackt = { ({1, 0}), ({0, 1}) }
dynamische Sprachlaufzeit
Obwohl Visual Basic technisch gesehen eine statische Sprache ist, verfügte es schon immer über sehr leistungsstarke dynamische Funktionen, wie z. B. die späte Bindung. Visual Studio 2010 verfügt über eine neue Plattform namens Dynamic Language Runtime (DLR), die es einfacher macht, dynamische Sprachen zu erstellen – und zwischen ihnen zu kommunizieren. Visual Basic 2010 wurde aktualisiert, um das DLR in seinen späten Ordnern vollständig zu unterstützen, sodass Entwickler Bibliotheken und Frameworks verwenden können, die in anderen Sprachen (wie IronPython/IronRuby) entwickelt wurden.
Ein herausragender Vorteil dieser Funktion besteht darin, dass sich syntaktisch nichts geändert hat (tatsächlich wurde im Compiler keine einzige Codezeile geändert, um diese Funktion zu unterstützen). Entwickler können wie in früheren Versionen von Visual Basic weiterhin späte Bindungsvorgänge ausführen. Was sich geändert hat, ist der Code in der Visual Basic-Laufzeitumgebung (Microsoft.VisualBasic.dll), der nun die vom DLR bereitgestellte IDynamicMetaObjectProvider-Schnittstelle erkennt. Wenn ein Objekt diese Schnittstelle implementiert, erstellt die Visual Basic-Laufzeit eine DLR-CallSite und ermöglicht dem Objekt und der Sprache, die es bereitstellt, ihre eigene Semantik in den Vorgang einzufügen.
Die Python-Standardbibliothek enthält beispielsweise eine Datei namens random.py, die über eine Methode namens shuffle verfügt, mit der die Elemente in einem Array zufällig neu angeordnet werden können. Der Aufruf dieser Methode ist einfach:
Dim python As ScriptRuntime = Python.CreateRuntime()
Dim random As Object = python.UseFile(random.py)
Elemente dimmen = {1, 2, 3, 4, 5, 6, 7}
random.shuffle(items)
Zur Laufzeit erkennt Visual Basic, dass das Objekt IDynamicMetaObjectProvider implementiert und übergibt daher die Steuerung an den DLR, der dann mit Python kommuniziert und die Methode ausführt (wobei das in Visual Basic definierte Array als Parameter an die Methode übergeben wird).
Dies ist ein Beispiel für den Aufruf einer DLR-fähigen API, Entwickler können jedoch auch eigene APIs erstellen, die diese Funktionalität nutzen. Der Schlüssel liegt in der Implementierung der IDynamicMetaObjectProvider-Schnittstelle. In diesem Fall erkennen die Visual Basic- und C#-Compiler Objekte mit spezieller dynamischer Semantik. Bitte implementieren Sie diese Schnittstelle nicht manuell, es ist einfacher, von der System.Dynamic.DynamicObject-Klasse zu erben (die diese Schnittstelle bereits implementiert) und nur einige wenige Methoden zu überschreiben. Abbildung 3 zeigt ein vollständiges Beispiel für die Erstellung eines benutzerdefinierten dynamischen Objekts (eine Eigenschaftentasche, die scheinbar Eigenschaften im laufenden Betrieb erstellt) und die Verwendung der normalen späten Bindung von Visual Basic zum Aufrufen des Objekts. (Weitere Informationen zur Verwendung von DynamicObject finden Sie im hervorragenden Artikel von Doug Rothaus unter blogs.msdn.com/vbteam/archive/2010/01/20/fun-with-dynamic-objects-doug-rothaus.aspx.)
Abbildung 3 Erstellen Sie ein benutzerdefiniertes dynamisches Objekt und rufen Sie das Objekt mithilfe der späten Bindung von Visual Basic auf
Imports System.Dynamic
Modul Modul1
Sub Main()
Dim p As Object = New PropertyBag
p.Eins = 1
S.Zwei = 2
S.Drei = 3
Console.WriteLine(p.One)
Console.WriteLine(p.Two)
Console.WriteLine(p.Three)
Sub beenden
Klasse PropertyBag: Erbt DynamicObject
Private Werte als neues Wörterbuch (String, Ganzzahl)
Öffentliche Überschreibungsfunktion TrySetMember(
ByVal-Binder As SetMemberBinder,
ByVal-Wert (als Objekt) als boolescher Wert
Werte(binder.Name) = Wert
Gibt True zurück
Funktion beenden
Öffentliche Überschreibungsfunktion TryGetMember(
ByVal-Binder als GetMemberBinder,
ByRef-Ergebnis als Objekt) als boolescher Wert
Rückgabewerte.TryGetValue(binder.Name, Ergebnis)
Funktion beenden
Unterricht beenden
Endmodul
generische Varianz
Dies ist eine Funktion, die zunächst zwar komplex klingt (mit Begriffen wie Kovarianz und Kontravarianz), aber eigentlich ganz einfach ist. Wenn Sie ein Objekt vom Typ IEnumerable(Of Apple) haben und es IEnumerable(Of Fruit) zuweisen möchten, sollte dies zulässig sein, da jeder Apfel eine Frucht ist (erzwungen durch Vererbung). Leider wurde die generische Varianz vor Visual Basic 2010 im Compiler nicht unterstützt, obwohl sie tatsächlich in der Common Language Runtime (CLR) unterstützt wurde.
Schauen wir uns das Beispiel in Abbildung 4 an. In Visual Basic 2008 erzeugt der Code in Abbildung 4 einen Kompilierungsfehler in der Dim-enabledOnly-Zeile (oder, wenn Option Strict deaktiviert ist, eine Laufzeitausnahme). Die Problemumgehung besteht darin, die .Cast-Erweiterungsmethode wie folgt aufzurufen:
'Old way, the call to Cast(Of Control) is no longer necessary in VB 2010
Dim aktiviertOnly = FilterEnabledOnly(buttons.Cast(Of Control))
Dies ist nicht mehr erforderlich, da in Visual Basic 2010 die IEnumerable-Schnittstelle mithilfe des Out-Modifikators als kovariant markiert wurde:
Interface IEnumerable(Of Out T)
...
Schnittstelle beenden
Abbildung 4 Beispiel einer generischen Varianz
Option Strict On
Öffentliches Klassenformular1
Sub Form1_Load() verarbeitet MyBase.Load
Dimmen Sie Schaltflächen als neue Liste (von Schaltflächen) aus
{
Neuer Knopf mit
{
.Name = btnOk,
.Enabled = True
},
Neuer Knopf mit
{
.Name = btnCancel,
.Enabled = Falsch
}
}
Dim activateOnly = FilterEnabledOnly(buttons)
Sub beenden
Funktion FilterEnabledOnly(
ByVal steuert As IEnumerable(Of Control)
) Als IEnumerable(Of Control)
Rückkehr von c In-Steuerelementen
Wobei c.Enabled = True
Funktion beenden
Unterricht beenden
Das bedeutet, dass der generische Parameter T nun eine Variable ist (also zur Vererbung geeignet ist) und der Compiler sicherstellt, dass der Parameter nur dann verwendet wird, wenn der Typ von einer Schnittstelle stammt. Generische Parameter können auch inverse Variablen sein, das heißt, sie werden nur dort verwendet, wo sie eingegeben werden. Ein Typ kann tatsächlich beides haben. Beispielsweise verfügt der zuvor besprochene Func-Delegat sowohl über kontravariante Parameter (für das, was übergeben wird) als auch über kovariante Parameter (für den Rückgabetyp):
Delegate Function Func(Of In T, Out R)(ByVal param As T) As R
Sie können In- und Out-Modifikatoren für benutzerdefinierte Schnittstellen und Delegaten verwenden. Viele gängige Schnittstellen und Delegaten in .NET Framework 4 sind als Variablen gekennzeichnet; gängige Beispiele sind alle Action/Func-Delegaten, IEnumerable(Of T), IComparer(Of T), IQueryable(Of T) usw.
Das Tolle an der generischen Varianz ist, dass Sie sich um diese Funktion überhaupt keine Sorgen machen müssen – wenn sie ihre Aufgabe erfüllt, werden Sie sie nie bemerken. Situationen, die früher zu Compilerfehlern führten oder den Aufruf von .Cast(Of T) erforderten, funktionieren in Visual Basic 2010 einwandfrei.
Verbesserte optionale Parameter
Optionale Parameter bieten eine nützliche Effizienzfunktion, die es Entwicklern ermöglicht, flexiblere Methoden zu erstellen und eine Klasse nicht mit vielen Methodenüberladungen zu überladen. In der Vergangenheit gab es eine leichte Einschränkung, dass optionale Parameter nicht null sein durften (und auch nicht von einem nicht internen Strukturtyp sein durften). Mit Visual Basic 2010 können Sie jetzt optionale Parameter eines beliebigen Werttyps definieren:
Sub DisplayOrder(ByVal customer As Customer,
ByVal orderID As Integer,
Optionale ByVal-Einheiten As Integer = 0,
Optional ByVal backgroundColor As Color = Nothing)
Sub beenden
In diesem Beispiel sind Einheiten vom Typ „Nullable(Of Integer)“ und „backgroundColor“ ist ein nicht inhaltsbezogener Strukturtyp, sie werden jedoch weiterhin als optionale Parameter verwendet. Visual Basic 2010 bietet außerdem eine bessere Unterstützung für generische optionale Parameter.
Eingebettete Interop-Typen
Eine häufige Schwäche von Anwendungen, die COM-Interop ausführen, ist die Notwendigkeit, eine Primary Interop Assembly (PIA) zu verwenden. Eine PIA ist eine .NET-Assembly, die als Runtime Callable Wrapper (RCW) für eine COM-Komponente fungiert und über eine eindeutige GUID verfügt, die sie identifiziert. Die .NET-Assembly kommuniziert mit der PIA, die dann das erforderliche Marshalling durchführt, um Daten zwischen COM und .NET zu verschieben.
Leider können PIAs die Bereitstellung erschweren, da es sich um zusätzliche DLLs handelt, die auf Endbenutzercomputern bereitgestellt werden müssen. Sie können auch Versionsprobleme verursachen – wenn Sie beispielsweise möchten, dass Ihre Anwendung sowohl mit Excel 2003 als auch mit Excel 2007 funktioniert, müssen Sie beide PIAs mit Ihrer Anwendung bereitstellen.
Die eingebettete Interop-Typ-Funktion wird direkt in die Anwendung eingebettet, jedoch nur die Typen und Mitglieder aus der PIA, die unbedingt erforderlich sind, sodass keine Notwendigkeit besteht, die PIA auf dem Computer des Endbenutzers bereitzustellen.
Um diese Funktion für ein vorhandenes Objekt zu aktivieren (sie ist standardmäßig für neue Referenzen aktiviert), wählen Sie die Referenz im Projektmappen-Explorer aus und ändern Sie die Option „Interop-Typen einbetten“ im Eigenschaftenfenster (siehe Abbildung 5). Wenn Sie alternativ mit dem Ming-Befehlszeilen-Compiler kompilieren, verwenden Sie den Schalter /l (oder /link) anstelle von /r und /reference.
Abbildung 5: Aktivieren eingebetteter Interop-Typen im Projektmappen-Explorer
Nach der Aktivierung dieser Funktion ist die Anwendung nicht mehr auf PIA angewiesen. Wenn Sie die Assembly in Reflector oder ildasm öffnen, werden Sie tatsächlich feststellen, dass es überhaupt keinen Verweis auf die PIA gibt.
Mehrere Ziele
Das Beste an allen Funktionen in Visual Basic 2010 ist, dass Sie sie sogar in Projekten verwenden können, die auf .NET Framework 2.0 bis .NET Framework 3.5 abzielen. Dies bedeutet, dass Funktionen wie implizite Zeilenfortsetzungszeichen, Array-Literale, Sammlungsinitialisierer, Anweisungs-Lambdas, automatisch implementierte Eigenschaften usw. in vorhandenen Projekten verfügbar sind, ohne dass .NET Framework 4 neu ausgerichtet werden muss.
Die Ausnahme bilden eingebettete Interop-Typen, die auf Typen basieren, die nur in .NET Framework 4 verfügbar sind. Wenn Sie daher auf die .NET Framework-Versionen 2.0 bis 3.5 abzielen, können Sie diese Funktion nicht verwenden. Darüber hinaus werden als Variablen markierte Typen nur so markiert, wie sie in .NET Framework 4 waren. Wenn Sie also im vorherigen Beispiel auf die Versionen 2.0 bis 3.5 abzielen, müssen Sie immer noch .Cast(Of T) aufrufen. Wenn Sie jedoch auf diese früheren Versionen abzielen, können Sie Ihre eigenen Variablentypen erstellen (mithilfe der In/Out-Modifikatoren).
Um das aktuelle Zielframework Ihrer Anwendung zu ändern, doppelklicken Sie auf „Meine Projekte“, klicken Sie auf die Registerkarte „Kompilieren“, klicken Sie auf „Erweiterte Kompilierungsoptionen“ und wählen Sie dann aus dem Kombinationsfeld unten aus.
Es gibt tatsächlich keinen Ming-Befehlszeilenschalter, um diese Funktion beim Kompilieren über die Ming-Befehlszeile zu aktivieren. Tatsächlich prüft der Compiler, welche Assembly die Definition von System.Object (normalerweise mscorlib) bereitstellt und auf welches Framework die Assembly abzielt, und markiert dann diesen Wert in der Ausgabeassembly. (Der Compiler verwendet denselben Mechanismus beim Generieren von Silverlight-Assemblys.) Wenn Sie eine IDE verwenden, geschieht dies alles transparent, sodass Sie sich normalerweise keine Sorgen machen müssen.
Willkommen zum Ausprobieren
Wie Sie sehen, verfügt Visual Basic 2010 über viele leistungsstarke Funktionen, die es Ihnen ermöglichen, produktiver zu sein, während Sie weniger Codezeilen schreiben und dem Compiler mehr Arbeit überlassen. In diesem Artikel habe ich nur Sprachfunktionen besprochen, es gibt jedoch unzählige großartige Verbesserungen an der Visual Basic 2010-IDE. Nachfolgend sind einige Verbesserungen aufgeführt:
Navigieren Sie zu
Zitate hervorheben
aus der Nutzung entstehen
Besseres IntelliSense (Teilstring-Abgleich, Camelcase-Suche, Vorschlagsmuster – nützlich, um zunächst Ihren Entwicklungsstil zu testen)
Unterstützung mehrerer Monitore
Zoom
Das Visual Basic-Team ist gespannt auf Ihr Feedback zu unseren Bemühungen, Visual Basic zu verbessern. Senden Sie uns daher bitte Ihre Kommentare und Fragen zu Microsoft Connect. Um mehr über die Sprach- und IDE-Funktionen zu erfahren, sehen Sie sich den Inhalt unter msdn.com/vbasic an, der Artikel, Beispiele und Anleitungsvideos enthält. Der beste Weg zum Lernen besteht natürlich darin, sich mit dem Produkt auseinanderzusetzen und es zu verwenden. Es ist also Zeit, es zu installieren und auszuprobieren.