Die Community zu .NET und Classic VB.
Menü

Neues in Visual Basic 2005

 von 

Übersicht 

Dieser Artikel erläutert viele der neuen Sprachmerkmale in Visual Basic 2005, des .NET Frameworks Version 2.0 und der neuen Ausgabe des Visual Studios.

Mit freundlichen Grüßen
Daniel Noll ()

Überblick  

Es sind mittlerweile bereits zwei Monate vergangen, seit die englische Version des neuen Visual Studios 2005 erschienen ist. Die Veröffentlichung der deutschen Version ist für den 8. Februar 2006 geplant. Darum wird es Zeit, die Neuerungen etwas genauer unter die Lupe zu nehmen.

Im Gegensatz zum Wechsel von Visual Studio .NET 2002 nach 2003 gibt es dieses Mal zusätzlich einige Änderungen an der Produktpalette. Die einzelnen Sprachpakete wurden zur Standard-Edition eingeschmolzen, die alle vier aktuellen Microsoft .NET-Sprachen enthält. Zusätzlich zur erhalten gebliebenen Professional-Variante gibt es eine neue Edition für Office-Entwickler, welche jedoch nur mit zwei Sprachen, nämlich C# und Visual Basic .NET, auskommen muss. An der oberen Spitze befinden sich die Team System Editionen „für Entwickler“, „für Architekten“ und „für Software-Tester“. Zusätzlich zu diesen Versionen bietet Microsoft noch die Express-Editionen (Visual Basic 2005 Express Edition: http://msdn.microsoft.com/vstudio/express/vb/) an, die auf Hobbyprogrammierer und Einsteiger zugeschnitten sind. Das Interessante an diesen, jeweils auf eine Sprache begrenzten Paketen ist, dass Microsoft sie (zumindest die englischen Versionen) ein Jahr lang kostenlos und ohne Einschränkungen der Verteilung der damit erstellten Programmen, zur Verfügung stellt. Die Express Editionen stehen den „großen“ Editionen für einfache Aufgaben in Nichts nach, etwas fortgeschrittenere Dinge wie die Unterstützung mobiler Geräte, der grafische Klassendesigner, eine Vielzahl der Debugfenster und die Unterstützung für Erweiterungen der IDE fehlen hingegen leider. Aufmerksamen Lesern mag vielleicht bereits schon aufgefallen sein, dass die Bezeichnung „.NET“, die die letzten zwei Ausgaben des Visual Studios schmückte, weggefallen ist.

Neues in der Sprache Visual Basic  

Im Gegensatz zum Sprung von 1.0 auf 1.1 hat sich seit 2003 einiges in der Sprache Visual Basic verändert. Teilweise sind brandneue Funktionen des neuen .NET Frameworks in die Sprache eingeflossen, teilweise wurde Visual Basic aber auch um schon aus C# bekannte Merkmale erweitert. Leider hat Microsoft erneut Funktionsmerkmale in C# eingebaut, die den VB-Programmierern verschlossen bleiben, darunter anonyme Methoden und Iteratoren mit dem yield-Schlüsselwort.

Generische Klassen (Generics)

Die wohl auffallendste Neuerung in Visual Basic .NET 2.0 sind generische Klassen (oder auf englisch auch „Generics“). Am Besten versteht man Generics, wenn man betrachtet, wie die Listen-Klassen aus den vorhergehenden .NET-Versionen dem Programmierer es ermöglichen, sie mit verschiedenen Typen zu befüllen:

Dim liste As New Collections.ArrayList()

' Add definiert als: Add(Value As Object) As Integer
liste.Add(3)
liste.Add(4)
liste.Add("Gar nicht gut")

Dim test As Integer = CInt(liste(0))
For Each i As Integer In liste
    System.Console.WriteLine(i)
Next

Listing 1

Wie das Beispiel zeigt, ist die Add-Funktion so definiert, dass wir ihr alles übergeben können, was wir wollen. Auf diese Weise kann die Klasse allgemein, also unabhängig von einem Typ verwendet werden. Leider kann es jedoch auch wie im obigen Beispiel geschehen, dass einmal ein Objekt des falschen Typs in der Aufzählung landet, was dann beim Auslesen zu einer InvalidCastException führt. Zusätzlich müssen wir, sofern Option Strict aktiviert ist (Anmerkung: was es auch sein sollte), jedes Mal das zurückgegebene Object zurück in einen Integer verwandeln. Die ArrayList-Klasse ist aus diesen Grunde also nicht typsicher.

Die .NET-Generics geben uns die Möglichkeit, Klassen so zu schreiben, dass sie für mehrere Typen verwendet werden können, aber dennoch typsicher sind. Schauen wir uns also einmal eine der bereits im .NET Framework enthaltenen generischen Klassen an:

Dim liste As New Collections.Generic.List(Of Integer)
liste.Add(3)
liste.Add(4)
liste.Add("Bäääätsch, geht nicht...")    'Nicht möglich

Dim test As Integer = liste(1)
For Each i As Integer In liste
    System.Console.WriteLine(i)
Next

Listing 2

Hier sehen wir zuerst einmal, wie wir eine der bereits in .NET 2.0 vorhandenen generischen Klassen verwenden können. In den Klammern nach dem Typ folgt, im Fall dieser Liste, der Typ den wir gerne in die Liste packen möchten, angeführt vom Schlüsselwörtchen Of.

Die Vorteile liegen klar auf der Hand. Wir sind nicht mehr in der Lage, eine Variable eines anderen Typs als Integer in die Liste einzufügen, da der Compiler eine Fehlermeldung beim Übersetzen ausgibt. Außerdem erhalten wir von der Liste direkt einen Integer zurück, so dass das lästige Konvertieren entfällt. Selbstverständlich können wir auch selbst allgemeine Klassen definieren:

Class Stack(Of TYPE)
    Private list As New List(Of TYPE)

    Public Function Pop() As TYPE
        Dim index As Integer = list.Count - 1
        Dim retval As TYPE = list(index)
        list.RemoveAt(index)

        Return retval
    End Function

    Public Sub Push(ByVal item As TYPE)
        list.Add(item)
    End Sub
End Class

Listing 3

In der ersten Zeile des Beispiels wird eine (voll funktionsfähige) generische Stack-Klasse definiert. Die Syntax der Deklaration ist ähnlich wie bei der Verwendung der Klasse, nach dem Of-Schlüsselwort folgt hier jedoch anstatt eines Typen ein Platzhalter für einen solchen. Diesen Platzhalter können wir nun dort verwenden, wo wir ansonsten einen Typen verwendet hätten.

Im Gegensatz zu den aus C++ bekannten Templates, findet die Spezialisierung der generischen Klasse auf einen Typen nicht zur Kompilierzeit, sondern zur Laufzeit statt. Dies hat den Vorteil, dass die ausführbare Datei nicht so stark anwächst, wie dies bei Verwendung der Templates in C++ der Fall wäre, da diese für jeden verwendeten Typ eine komplette Variante der Klasse mit sich herumträgt. Dies hat leider aber auch den Nachteil, dass die Klassendefinitionen absolut typsicher sein müssen: so ist es in einer generischen .NET-Klasse schlichtweg unmöglich, zwei Varianten der Typen-”Platzhalter” zu addieren, da die CLI in diesem Fall sicherstellen müsste, dass jeder verwendete Typ wirklich addierbar ist. Dies ist jedoch unmöglich, da die Spezialisierung der Klasse erst zur Laufzeit stattfindet, der Visual Basic-Compiler kann an dieser Stelle nichts Anderes machen, als jede Addition zu verbieten, währenddessen ein C++-Compiler „weiß”, welche Typen im Einsatz sind und dementsprechend erst einen Fehler auslöst, sobald einer der Typen wirklich nicht addierbar ist. Dieser gravierende Nachteil wird durch Contraints gelindert, jedoch nicht gelöst, mit denen man beschränken kann, welche Typen man als Typ-Platzhalter verwenden kann:

Dim s1 As New Stack(Of String)
    ' Fehler, Integer ist keine Klasse, sondern eine Struktur
    Dim s2 As New Stack(Of Integer)
End Sub

Class Stack(Of TYPE As {Class, Icomparable})

Listing 4

Auf diese Weise lassen sich die eingesetzten Typen auf einen bestimmten Satz an Interfaces beschränken, da es allerdings kein IAddable gibt, bleiben dem Programmierer arithmetische Operationen dennoch verschlossen.

Das folgende Beispiel zeigt, wie sich unabhängig von einer generischen Klasse, generische Methoden und Funktionen definieren lassen. Über die etwas umständliche Umsetzung der Vergleiche lässt sich jedoch diskutieren:

Sub Main()
    Console.WriteLine(Compare(Of String)("Ein belegtes Brot mit Schinken", _
        "Ein belegtes Brot mit Ei"))
    Console.WriteLine(Compare(Of Integer)(2 * 2, 4))
End Sub

Function Compare(Of Typ As IComparable)(ByVal wert1 As Typ, _
        ByVal wert2 As Typ) As Boolean
    Return (wert1.CompareTo(wert2) = 0)
End Function

Listing 5

Continue

Nach Jahren des Wartens unterstützt unterstützt Visual Basic nun endlich auch das aus vielen anderen Programmiersprachen bekannte Continue. Continue dient dazu den aktuellen Schleifendurchlauf abzubrechen und gleich mit dem Nächsten fortzufahren. Dieses Beispiel zeigt, wie man auf sehr unelegante Weise sämtliche Zahlen von 0 bis 50 ausgeben kann, die sich nicht durch 5 teilen lassen:

For i As Integer = 0 To 50
    If (i Mod 5 = 0) Then Continue For
    Console.WriteLine(i)
Next

Listing 6

Die Umsetzung der Continue-Anweisung in Visual Basic ist sogar ein wenig leistungsfähiger, als die C#'s. Dies kommt dadurch, dass hinter dem Continue-Schlüsselwort noch der Schleifentyp angegeben werden muss. Hiermit ist es auch möglich z.B. in einer For-Schleife einen Durchlauf einer umfassenden While-Schleife zu überspringen, in dem man einfach ein Continue While angibt. Doch das Ganze geht noch einen Schritt weiter: in zwei verschachtelten For-Schleifen mit den Schleifenvariablen i und j, kann durch die Angabe von entweder Continue For i oder Continue For j, die Schleife ausgewählt werden, deren Durchlauf übersprungen werden soll.

Der IsNot-Operator

If Not t Is Nothing Then

Wenn man in Visual Basic .NET 1.0/1.1 überprüfen wollte, ob eine Referenz auf ein Objekt weißt, so durfte man das oben stehende Konstrukt verwenden, welches nicht nur umständlich zu schreiben ist, sondern auch gehörig gegen den normalen menschlichen Sprachsinn geht. Aus diesem Grund hat Microsoft den grammatik-bedachten Programmierern unter uns den IsNot-Operator geschenkt, mit dem das Ganze dann so aussieht:

If t IsNot Nothing Then

Der Using-Block

Ein Problem bei dem Umgang mit unverwalteten Ressourcen ist, dass das .NET Framework alleine nicht dazu in der Lage ist, diese möglichst schnell freizugeben. Dies wird vom .NET Framework über die manuell aufrufbare Dispose-Methode einer Klasse erledigt. Jedoch gibt es Fälle, in denen es nur sehr umständlich ist, ein Objekt freizugeben, wie zum Beispiel im Fall einer Exception. Aus diesem Grund wurde mit der Sprachversion 2.0 das Using-Konstrukt eingeführt:

Try
    Using a As New System.Drawing.Pen(Drawing.Color.Aquamarine)
        a.Alignment = Drawing.Drawing2D.PenAlignment.Left
        ' Was auch immer...

        Dim i As Double = 1 / 0
    End Using
Catch ex As Exception
End Try

Listing 7

Dadurch, dass der Stift an dieser Stelle über den Using-Block definiert wird, wird garantiert, dass die Dispose-Methode auf jeden Fall aufgerufen wird, wenn dieser Block verlassen wird. Dies kann im normalen Verlauf des Codes geschehen, oder aber auch wie hier, durch eine Exception.

Nullable Types

Hin und wieder kommt es vor, dass ein Wertetyp (also zum Beispiel eine Struktur) keinen festgelegten Wert besitzen soll. Bei Referenztypen kommt es hier nicht zu Problemen, da man lediglich die Referenz auf Nothing setzen muss, was aber bei Wertetypen bisher nicht funktionierte. Die im .NET Framework bisher häufig anzutreffende Möglichkeit einen „Leer“-Wert zu simulieren, zeigt sich zum Beispiel an der System.Drawing.Size-Struktur, die ein Empty-Mitglied enthält. Seit .NET 2.0 gibt es hierzu eine Alternative:

Dim n As New Nullable(Of Drawing.Size)

n = New Drawing.Size(1, 2)
Console.WriteLine("Versuch 1: {0} {1}", n, n.HasValue)

n = Nothing
Console.WriteLine("Versuch 2: {0} {1}", n, n.HasValue)

Listing 8

Durch den Nullable-Wrapper um das Size-Object ist es nun möglich, der Struktur Nothing zuzuweißen. Es ist jedoch nicht möglich, über den = oder den is-Operator auf einen Nothing-Wert zu prüfen, hierzu gibt es die HasValue-Eigenschaft.

Vorzeichenlose Typen

Visual Basic-Programmierer kamen bisher nicht in den Genuss der vorzeichenlosen Integer-Datentypen des .NET Frameworks (UInt16, UInt32, UInt64), da es dank mangelnder Compiler-Unterstützung keine Möglichkeit gab, darauf zuzugreifen. Dies hat sich mit Visual Basic 2005 geändert:

Dim i1 As UInteger = 1234
Dim i2 As UInteger = CUInt(i1 – 2468) ' Führt zu einer Overflow-Exception

Listing 9

Als nette Beigabe gibt es zu den Typen UShort, UInteger und ULong noch ein vorzeichenbehaftetes Byte, welches als SByte verwendet werden kann.

Unterschiedliche Sichtbarkeitsbereiche für Eigenschaften

Eine weitere nervige Eigenschaft der .NET-Versionen 1.0/1.1 wurde dadurch entfernt, dass die Set- und Get-Zugriffsmethoden einer Property nun endlich unterschiedliche Sichtbarkeitsbereiche besitzen dürfen:

Public Property EinWert() As Integer
    Get
    End Get
    Private Set(ByVal value As Integer)
    End Set
End Property

Listing 10

In diesem Beispiel kann der Wert von überall ausgelesen werden, jedoch nur innerhalb der Klasse geschrieben werden.

Operatorüberladung

Operatorüberladung ist die Technik für selbst geschriebene Klassen eigenen Programmcode für die einzelnen Operatoren zu definieren, damit sich diese ähnlich den eingebauten Klassen verhalten. Ein Beispiel hierfür ist die folgende Vektorklasse:

Class Vector
    Private x, y, z As Integer

    Public Sub New(ByVal x As Integer, ByVal y As Integer, 
            ByVal z As Integer)
        Me.x = x : Me.y = y : Me.z = z
    End Sub

    Public Shared Operator +(ByVal wert1 As Vector, ByVal wert2 As Vector) 
            As Vector
        Return New Vector( _
            wert1.x + wert2.x, _
            wert1.y + wert2.y, _
            wert1.z + wert2.z)
    End Operator
End Class

Listing 11

Instanzen dieser Klasse können nun einfach, wie zum Beispiel zwei Integer, miteinander addiert werden. Bei dem hier überschriebenen Plus-Operator handelt es sich um einen binären Operator, da er mit zwei Werten rechnet. Verschiedene andere Operatoren, wie zum Beispiel Not sind jedoch lediglich unär, d.h. sie arbeiten nur mit einem Wert. Einige der zur Überladung verfügbaren Operatoren können nur im Paar überladen werden, wie zum Beispiel der = und <>-Operator oder der > und <-Operator.

Neben diesen einfachen Arithmetik-, Vergleichs- und Logikoperatoren gibt es noch die Möglichkeiten Operatoren für die Umwandlung in andere Typen zu definieren. In diesem Fall muss nach dem Operator-Schlüsselwort CType eingesetzt werden. Im Gegensatz zu den anderen Überladungsformen muss beim Überladen von CType noch ein weiterer Parameter angeben werden, der den Typ der Umwandlung bestimmt. Mögliche Werte sind Widening oder Narrowing. Mit Widening teilt man dem Compiler mit, dass die Umwandlung zur Laufzeit auf jeden Fall fehlerfrei durchgeführt werden kann und dass kein Informationsverlust vorhanden ist. Beispiele für eine Widening-Umwandlung wären also die Umwandlungen von Byte nach Short oder von Integer nach Long. Narrowing bedeutet das genaue Gegenteil: hier muss der Compiler damit rechnen, dass ein Fehler auftritt oder Informationen verloren gehen, weswegen Narrowing-Typumwandlungen nicht implizit durchgeführt werden.

Public Shared Widening Operator CType(ByVal wert As Vector) As VectorDouble
    Return New VectorDouble(wert.x, wert.y, wert.z)
End Operator

Public Shared Narrowing Operator CType(ByVal wert As Vector) As VectorShort
    Return New VectorShort(wert.x, wert.y, wert.z)
End Operator

Listing 12

Partielle Klassen

Ein interessantes neues Funktionsmerkmal des .NET Frameworks in der Version 2.0 ist die Möglichkeit Klassen in mehreren Teilen zu definieren. Eine Klasse, die mit dem Partial-Schlüsselwort definiert wird, kann in beliebig viele Teile zerbrochen werden. Einen wahren Vorteil bringt dies erst, wenn man beginnt, diese Teile auf mehrere Dateien zu verteilen. Auf diese Art und Weise kann man die Definitionen einer Klasse aufs wichtigste konzentrieren oder die Methoden und Variablendeklarationen nach Aufgaben sortieren.

Partial Class test
    Sub HalloWelt()
    End Sub
End Class
Partial Class test
    Sub SingEinLied()
    End Sub
End Class

Listing 13

Partielle Klassen kommen beispielsweise beim Visual Studio Form-Designer zum Einsatz. Hier wird der Code, der benötigt wird, um die Controls auf ein Fenster zu zaubern einfach in einer zusätzlichen Datei gespeichert. Als Programmierer bekommt man dann lediglich das gewünschte Ergebnis, aber keine Zeile Code zu sehen (den man sich selbstverständlich in der zusätzlichen Datei ansehen kann).

Custom Events

Eine weitere größtenteils unbekannte Neuerung in Visual Basic 2005 sind Custom Events, die es dem Programmierer erlauben genauer zu definieren, was beim Hinzufügen eines Handlers zu einem Event, dem Entfernen eines solchen und beim Auslösen eines Events geschehen soll. Dadurch, dass ein Event als Custom deklariert wird, teilen wir dem Compiler mit, dass er die Codegenerierung der Verwaltung für das Event außer Kraft setzen soll. Aus diesem Grund muss sich der Programmierer darum selbst kümmern.

Class HalloWelt
    Private HalloWeltEventList As List(Of EventHandler)

    Public Custom Event HalloWeltAusgelöst As EventHandler
        AddHandler(ByVal Value As EventHandler)
            Console.WriteLine("Hallo Event-Listener")
            HalloWeltEventList.Add(Value)
        End AddHandler
        RemoveHandler(ByVal Value As EventHandler)
            Console.WriteLine("Kein Schwein ruft mich an :-(")
            HalloWeltEventList.Remove(Value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            Console.WriteLine("Schöne Grüße!")

            For Each handler As EventHandler In HalloWeltEventList
                If handler IsNot Nothing Then
                    handler.BeginInvoke(sender, e, Nothing, Nothing)
                End If
            Next
        End RaiseEvent
    End Event
End Class

Listing 14

Dieses Beispiel implementiert ein Event, das nicht den Thread blockiert, wenn es aufgerufen wird. Dies geschieht dadurch, dass die Verwaltung der Event-Handler übernommen wird. Der RaiseEvent-Code wird ausgeführt, wenn das Event ausgelöst wird. Im Fall dieses Beispiels wird die Liste der Handler durchgegangen und jeder in seinem eigenen Thread gestartet, so dass der Hauptthread, im Gegensatz zum Verhalten bei einem normalen Event, ungestört weiterläuft.

Der My-Namespace

In der Vergangenheit haben sich viele der verbleibenden Visual Basic 6-Programmierer und Fanatiker über die Tatsache beschwert, dass Visual Basic .NET keine wirkliche RAD-Programmiersprache sei. Vieles, was sich unter VB6 mit wenigen Befehlen erledigen ließ, bräuchte in der .NET-Version erheblichen Einarbeitungsaufwand in das .NET Framework. Das My-Schlüsselwort ist ein Schritt entgegen dieses Trends. Es stellt viele häufig genutzte Funktionen in Form eines einzigen Befehls zur Verfügung.

My verhält sich wie ein Namespace und ist in mehrere Unternamespaces eingeteilt, die die Befehle für unterschiedliche Aufgaben enthalten. So gibt es zum Beispiel My.Application, in dem verschiedene Informationen über die eigene Anwendung zu finden sind, wie zum Beispiel die Kommandozeilenargumente. My.Computer fasst viele Funktionen und Operationen rund um den PC auf dem das Programm läuft zusammen. So findet man zum Beispiel unter My.Computer.Info viele Informationen über das installierte System, unter My.Computer.Registry einige Funktionen, mit denen sich in wenigen Befehlen ein Registry-Zugriff erledigen lässt, oder unter My.Computer.FileSystem häufig verwendete Kommandos des Dateisystems (zum Beispiel zum Schreiben eines Strings in eine Datei mit nur einem Befehl). Weiterhin gibt es noch Unternamespaces für den Umgang mit Audiodateien, den Eingabegeräten des Systems, der Zwischenablage, Informationen über den aktuellen User, eine Möglichkeit auf sehr einfache Weise seine Programmeinstellungen abzulegen und vieles mehr. Hier einige Beispiele zur Programmierung mit dem My-Namespace.

Dim info As String = _
    "Das Programm läuft unter " & My.Computer.Info.OSFullName & _
    " auf einem PC mit " & My.Computer.Info.TotalPhysicalMemory & _
    "Byte Speicher"
My.Computer.FileSystem.WriteAllText( _
    My.Computer.FileSystem.SpecialDirectories.Desktop & "\info.txt", _
    info, False)

Listing 15

Der My-Namespace ist derzeit ein vollkommen auf Visual Basic begrenztes Funktionsmerkmal. In der Praxis ist My allerdings sehr praktisch, so praktisch, dass Programmierer der syntaktisch und technisch VB absolut überlegenen Programmiersprache C# Microsofts Entscheidung My nicht in C# verfügbar zu machen, als gemyn und mys bezeichnen.

Neues im .NET Framework Version 2.0  

Ein großer Haufen Veränderungen sind alleine durch die Umstellung der .NET Framework-Klassen auf Generics in die Klassenbibliotheken eingeflossen. Selbst verständlich bleiben die älteren Klassen aus Kompatibiltätsgründen erhalten. Am Auffälligsten sind wohl die neuen Aufzählungsklassen, zu finden unter System.Collections.Generic, die die alten Aufzählungsklassen ersetzen sollen. Hier als Beispiel die Verwendung der neuen Dictionary-Klasse, die zur Speicherung von Schlüssel/Wert-Paaren gedacht ist:

Dim dir As New Collections.Generic.Dictionary(Of String, Integer)
dir.Add("SinnDesLebens", 42)
dir.Add("UngefährPi", 3)

Dim ienum As _
    Collections.Generic.Dictionary(Of String, Integer).Enumerator = _
    dir.GetEnumerator()
While (ienum.MoveNext)
    Console.WriteLine("{0}:{1}", _
        ienum.Current.Key, _
        ienum.Current.Value)
End While

Listing 16

Zusätzlich gibt es noch einen riesigen Haufen anderer Änderungen, die hier vorzustellen den Rahmen dieses Artikels sprengen würde. Einige interessante Punkte, will ich dennoch aufführen:

  • Die in .NET 1.0/1.1 etwas spartanisch ausgeartete Console-Klasse wurde um eine Vielzahl neuer Mitglieder erweitert. Mit diesen neuen Methoden kann man Position, Größe und Titel des Konsolenfenster und die Cursorposition setzen, die Farbe der Ausgabe verändern und einiges mehr.
  • Über die NetworkChange-Klasse kann ein Programmierer Veränderungen am Netzwerkstatus abfragen. Zusätzlich existieren einige neue Klassen, die es ermöglichen Informationen über die Netzwerkverbindungen eines Systems auszulesen.
  • Dank der Klassen WebRequest, WebResponse und WebClient kann das .NET Framework nun auch das File Transfer Protocol (FTP) verwenden
  • Für alle, die in den vorhergehenden .NET-Versionen zu faul waren, ihre eigenen Ping-Pakete zusammenzubasteln, gibt es nun eine Ping-Klasse.
  • Die IO-Klassen sind einigen Verbesserungen unterlaufen. Im System.IO.Ports-Namespace befinden sich einige neue Klassen, die es ermöglichen auf die serielle Schnittstelle zuzugreifen und im System.IO.Compression-Namespace findet man nun Klassen, die die Komprimierung von Streams steuern.

Änderungen rund um Windows Forms 2.0

Auch auf der Seite der Windows Forms hat sich einiges getan. Es gibt eine Vielzahl neuer Controls und Komponenten, wobei auch teilweise alte Controls durch Neue mit verbesserter Funktionalität ersetzt wurden.

Eines der schon zu VB6-Zeiten häufig verwendeten OCX-Controls hat nun endlich ausgedient, da die neuen Windows Forms ein natives WebBrowser-Control mitbringen. Sehr schön ist, dass das Control sehr viele Einstellungsmöglichkeiten bietet, wie zum Beispiel die Option das Kontextmenu des Browsers zu deaktivieren, was mit Visual Basic 6-Mitteln und dem OCX-Control nur schwer möglich war. Das DataGrid-Control musste dem DataGridView-Control weichen, welches deutlich mehr Einstellungs- und Erweiterungsmöglichkeiten bietet und mehr Anzeigemöglichkeiten für verschiedene Datentypen mit sich bringt. Ähnlich dem DataGrid erging es auch dem Splitter-Controls aus .NET 1.0/1.1, es wurde durch den neuen SplitContainer ersetzt. Allerdings ist es relativ unwahrscheinlich, dass jemand dem Splitter-Control ernsthaft hinterher weinen wird, da es sich teilweise stark unlogisch verhielt. Der neue SplitContainer enthält zwei gegeneinander verschiebbare Panels, die sich mit Inhalt befüllen lassen. Ebenfalls neu ist die MaskedTextBox, die Daten in einem festlegbaren Format entgegennimmt. Hiermit plant Microsoft sämtlichen Autoren von „Wie schreibe ich mein eigenes Control?“-Artikeln das Wasser abzugraben, da die häufig als Beispiel zum Einsatz kommende „Nur-Zahlen“-Textbox kein sinnvolles Einsatzgebiet mehr hat.

Eine Kompletterneuerung haben auch die Menu- und Toolbar-Controls erhalten, wodurch die mit dem .NET Framework ausgelieferten Steuerelemente zum ersten Mal denen der Microsoft IDE fast gleichwertig sind. Als Ausgangspunkt dieser beiden UI-Elemente dient der Toolstrip-Container. Dieser bietet an jeder Seite ein ToolStripPanel, in denen sich ToolStrips, StatusStrips und MenuStrips anordnen lassen. Das Schöne dieser Strips ist, dass sie sich auch noch zu Laufzeit umsortieren und verschieben lassen. Eine der wenigen Funktionalitäten, die ich persönlich im Vergleich mit den IDE-Controls vermisse, ist die Möglichkeit, die ToolStrips in eigene Fenster zu entdocken.


Abbildung 1

Auch bei der Positionierung der Controls gibt es nun neue Möglichkeiten. In den vorhergehenden Versionen des .NET Frameworks ließen sich Controls nur durch Angabe von Position und Größe auf einem Container anordnen. Im Zusammenspiel mit den Dock und Anchor-Eigenschaften ist diese Methode auch für komplexe Forms durchaus ausreichend, wenn es jedoch daran geht, dass sich eine Tabelle auch beim Vergrößern und Verkleinern des Containers richtig verhält und die Controls beispielsweise richtig umbricht, wird es mit herkömmlichen Mitteln schwierig. Um dieses und andere Probleme zu lösen, gibt es in der Version 2.0 des Frameworks verschiedene Layout-Container. Eines davon ist das TableLayoutPanel, das eine Tabelle aus x mal y Tabellenpanels zur Verfügung stellt, die alle mit Steuerelementen befüllt werden können. Das Control übernimmt dann die Positionierung aller in ihm enthaltenen Steuerelementen. Das zweite verfügbare Layout-Control ist das FlowLayoutPanel, in welchem die enthaltenen Controls hintereinander angeordnet werden und so, falls benötigt, automatisch umgebrochen werden.

Auch das Visual Studio hat einige beachtliche Änderungen im Bezug mit den neuen Windows Forms erhalten. Sehr hilfreich für die Positionierung der Controls im Form-Editor sind die neuen SnapLines, die beim Verschieben eines Steuerelements zwischen dem zu positionierenden Control und anderen bereits vorhandenen Elementen angezeigt werden. Dabei werden auch Formränder, oder, wie in dem folgenden Bild zu sehen, die Basislinien der Schrift in Betracht gezogen.


Abbildung 2

Auf gefüllten Formen ist es manchmal schwer den Überblick zu behalten. Aus diesem Grund hat Microsoft dem Visual Studio-Formeditor eine neue Dokument-Übersicht spendiert, auf der sämtliche Elemente einer ausgewählten Form in einer Baumansicht angezeigt werden.


Abbildung 3

Ebenfalls neu sind Smart-Tags, die für einige der erweiterten Controls zur Verfügung stehen. Sie bieten eine einfache Zugriffsmöglichkeit auf die am meisten verwendeten Aktionen eines Steuerelements, wie hier im Beispiel eines ToolStripContainers zu sehen.


Abbildung 4

Neues rund um die Visual Studio 2005-IDE  

Eine Funktion, die umsteigende Visual Basic 6-Programmierer in den vorhergehenden Visual Studio-Versionen vermisst haben werden, ist die Möglichkeit Programmcode im Debug-Modus zu verändern. Mit dem Visual Studio 2005 ist das Edit&Continue-Verfahren zurückgekehrt. Ein weiteres der neuen Features dürfte VB6-Programmierern ebenso bekannt vorkommen: es ist endlich wieder möglich Projekte anzulegen, ohne diese direkt zu speichern. Es ist also endlich wieder möglich schnell Visual Basic zu öffnen um eine Idee auszuprobieren.

Auch das in den alten Versionen schon exzellente IntelliSense hat ein paar Verbesserungen erfahren. So besitzt jede IntelliSense-Box nun zwei Reiter, „Common“ und „All“. Unter Common befinden sich nur die am häufigsten verwendeten Funktionen, währenddessen „All“ alle zur Verfügung stehenden Operationen eines Objekts anzeigt. Ein neues groß beworbenes Funktionsmerkmal sind die so genannten Code Snippets, die nichts weiter als einfügbare Codefragmente darstellen. Ein solches Snippet kann man über den Unterpunkt „Insert Snippet“ im Kontextmenu des Codeeditors oder durch Strg+K, Strg+X einfügen.


Abbildung 5

Das Schöne an der Umsetzung des Visual Studios ist, dass die verschiedenen Felder des Snippets, die der Programmierer anpassen muss, auch wirklich ein kleines Eingabefeld erhälten. Verändert man einen Wert, so passen sich automatisch die korrespondierenden Felder an. Würden wir also im untenstehenden Fall eines CType-Operators String durch Integer ersetzen, so würde dies im gesamten Snippet passieren.


Abbildung 6

In den Code-Editor des neuen Visual Studio sind zusätzlich die bereits aus Office 2003 bekannten Smart Tags eingeflossen. Sie zeigen, je nach Fall mehr oder weniger sinnvolle Lösungswege für Fehler und Probleme an.


Abbildung 7

In der nun vorliegenden Version speichert das Visual Studio endlich auch AutoRevover-Informationen, die helfen, die IDE nach einem Absturz wieder in den vorhergehenden Zustand zu bringen. Glücklicherweise kommen diese Informationen nur selten zum Einsatz, da die Version 2005 ebenso wie die Vorgänger sehr stabil läuft.

Schlusswort  

Natürlich konnte dieser Artikel lediglich einige der wichtigsten Änderungen anreißen. Auch im Bereich ASP.NET und bei der Datenbindung in den Windows Forms hat sich Enormes getan, so dass diese Änderungen für diejenigen, die damit arbeiten, sicherlich einen Blick wert sind. Viele der Änderungen stecken selbstverständlich im Detail, so dass sie einzeln keine Erwähnung wert sind, aber zusammengefasst das Arbeiten mit dem neuen Framework bequemer als in den vorhergehenden Versionen machen werden.

Mit freundlichem Gruß
Daniel Noll

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.