![]() |
|
|||||
35.1.4 Attribute
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Mehrfachvererbung |
| Const-Mitgliedsfunktionen oder -Parameter. Const-Felder werden unterstützt. |
| Globale Variablen |
| Typedef |
| Konvertierung durch Erstellungsroutine |
| Standardargumente für Funktionsparameter |
C# und Java gehen auf gleiche Wurzeln zurück, daher ist es nicht überraschend, dass zwischen den beiden Sprachen Ähnlichkeiten vorhanden sind. Dennoch gibt es auch einige Unterschiede. Der größte Unterschied besteht darin, dass sich C# oberhalb der.NET-Frameworks und der .NET-Laufzeit befindet und Java den Frameworks und der Laufzeit von Java übergeordnet ist.
C# verfügt über primitivere Datentypen als Java. In der folgenden Tabelle werden die Java-Typen und deren C#-Äquivalente zusammengefasst:
| C#-Typ | Java-Typ | Kommentar |
| sbyte | byte | C#-byte hat kein Vorzeichen |
| short | short | |
| int | int | |
| long | long | |
| bool | Boolean | |
| float | float | |
| double | double | |
| char | char | |
| string | string | |
| object | object | |
| byte | Byte-Wert ohne Vorzeichen | |
| ushort | Short-Wert ohne Vorzeichen | |
| uint | Integer-Wert ohne Vorzeichen | |
| ulong | Long-Wert ohne Vorzeichen | |
| decimal | Finanzdaten-/Währungstyp |
In Java werden die primitiven und die objektbasierten Datentypen voneinander getrennt. Damit die primitiven Typen an der objektbasierten Welt teilhaben können (beispielsweise in einer Auflistung), müssen sie in einer Instanz einer Wrapperklasse platziert werden, und die Wrapperklasse wird anschließend in der Auflistung platziert.
C# geht dieses Problem anders an. In C# sind die primitiven Typen (wie bei Java) dem Stack zugeordnet, sie werden jedoch auch als von der ultimativen Basisklasse object abgeleitet betrachtet. Dies bedeutet, dass für die primitiven Typen Mitgliedsfunktionen definiert und aufgerufen werden können. Mit anderen Worten, der folgende Code ist zulässig:
using System; class Test { public static void Main() { Console.WriteLine(5.ToString()); } }
Die Konstante 5 weist den Typ int auf, das ToString()-Mitglied ist für den Typ int definiert, daher kann der Compiler einen Aufruf generieren und den int an die Mitgliedsfunktion übergeben, als handele es sich um ein Objekt.
Dies funktioniert prima, wenn der Compiler die Handhabung eines primitiven Typs kennt, jedoch nicht, wenn ein primitiver Typ mit den dem Heap zugeordneten Objekten einer Auflistung zusammenarbeiten muss. Immer dann, wenn ein primitiver Typ verwendet wird und ein Parameter vom Typ object erforderlich ist, führt der Compiler ein automatisches Boxing des primitiven Typs in einen dem Heap zugeordneten Wrapper durch. Hier ein Beispiel zum Boxing:
using System; class Test { public static void Main() { int v = 55; object o = v; // Boxing von v in o Console.WriteLine("Value is: {0}", o); int v2 = (int) o; // Unboxing zurück in int } }
In diesem Codeabschnitt wird der integer-Wert in ein object geboxt und der Mitgliedsfunktion Console.WriteLine() als Objektparameter übergeben. Das Deklarieren der Objektvariable erfolgt nur zur Verdeutlichung; im tatsächlichen Code würde v direkt übergeben, das Boxing würde auf Aufruferseite erfolgen. Der geboxte int-Wert kann durch eine cast-Operation extrahiert werden.
Die primitiven C#-Typen (mit Ausnahme von string und object) werden auch als Wertetypen bezeichnet, da Variablen dieser Typen tatsächliche Werte enthalten. Andere Typen werden Verweistypen genannt, da die zugehörigen Variablen Verweise enthalten.
In C# kann ein Programmierer das Typensystem durch Implementierung eines benutzerdefinierten Wertetyps erweitern. Diese Typen werden mit Hilfe des Schlüsselwortes struct implementiert und verhalten sich ähnlich wie die integrierten Wertetypen. Sie sind dem Stack zugeordnet, können Mitgliedsfunktionen aufweisen, und bei Bedarf wird ein Boxing oder Unboxing durchgeführt. Tatsächlich sind alle primitiven C#-Typen als Wertetypen implementiert, der einzige syntaktische Unterschied zwischen den integrierten Typen und den benutzerdefinierten Typen besteht darin, dass die integrierten Typen als Konstanten geschrieben werden können.
Damit sich die benutzerdefinierten Typen natürlich verhalten, können C#-Strukturen arithmetische Operatoren überladen, um numerische Operationen und Konvertierungen auszuführen, d. h., zwischen Strukturen und anderen Typen können implizite und explizite Konvertierungen erfolgen. C# unterstützt des Weiteren auch das Überladen von Klassen.
Ein struct wird mit Hilfe der gleichen Syntax geschrieben wie class, abgesehen davon, dass eine Struktur (neben der impliziten Basisklasse object) keine Basisklasse besitzen kann. Schnittstellen können jedoch implementiert werden.
C#-Klassen ähneln den Java-Klassen sehr stark. Im Hinblick auf Konstanten, Basisklassen und Erstellungsroutinen, statische Konstruktoren, virtuelle Funktionen, Ausblenden und Versionssteuerung, Mitgliedszugriff, ref- und out-Parameter sowie das Identifizieren von Typen bestehen jedoch Unterschiede.
Java verwendet zum Deklarieren einer Klassenkonstante static final. In C# wird static final durch const ersetzt. Zusätzlich fügt C# das Schlüsselwort readonly hinzu, das verwendet wird, wenn die Konstantenwerte zur Kompilierungszeit nicht ermittelt werden können. Readonly-Felder können nur über eine Initialisierungsroutine oder eine Klassenerstellungsroutine gesetzt werden.
C# verwendet sowohl für das Definieren der Basisklasse und die Schnittstellen einer Klasse als auch für das Aufrufen weiterer Erstellungsroutinen die C++-Syntax. Eine C#-Klasse kann folgendermaßen aussehen:
class MyObject: Control, IFormattable { public Control(int value) { this.value = value; } public Control() : base(value) { } int value; }
Anstelle eines statischen Initialisierungsblocks verwendet C# statische Erstellungsroutinen, die mit Hilfe des Schlüsselworts static geschrieben werden, das einer parameterlosen Erstellungsroutine vorangestellt wird.
In C# sind standardmäßig alle Funktionen nicht virtuell, um eine virtuelle Funktion zu erhalten, muss explizit virtual angegeben werden. Aufgrund dieser Tatsache gibt es keine finalen Methoden in C#, auch wenn das Äquivalent zu einer finalen Klasse mit Hilfe von sealed erreicht werden kann.
C# bietet eine bessere Versionsunterstützung als Java, woraus sich einige kleinere Änderungen ergeben. Die Methodenüberladung erfolgt statt nach Signatur nach Name, d. h., das Hinzufügen von Klassen zu einer Basisklasse wirkt sich nicht auf das Programmverhalten aus. Sehen Sie sich folgendes Beispiel an:
public class B { } public class D: B { public void Process(object o) {} } class Test { public static void Main() { D d = new D(); d.Process(15); // Aufruf durchführen } }
Wenn der Provider der Basisklasse eine Verarbeitungsfunktion mit größerer Übereinstimmung hinzufügt, ändert sich das Verhalten:
public class B { public void Process(int v) {} } public class D: B { public void Process(object o) {} } class Test { public static void Main() { D d = new D(); d.Process(15); // Aufruf durchführen } }
In Java führt dies zum Aufruf der Klassenimplementierung, was wahrscheinlich falsch ist. In C# setzt das Programm seine Arbeit fort.
Zur Handhabung des ähnlichen Falles für virtuelle Funktionen muss in C# die Versionssemantik explizit angegeben werden. Wenn es sich bei Process() um eine virtuelle Funktion der abgeleiteten Klasse handelt, würde Java annehmen, dass es sich bei jeder Basisklassenfunktion mit übereinstimmender Signatur um eine Basis für die virtuelle Funktion handelt, was in den meisten Fällen nicht stimmt.
In C# werden virtuelle Funktionen nur außer Kraft gesetzt, wenn das Schlüsselwort override verwendet wird. Weitere Informationen hierzu finden Sie in Kapitel 11, Versionssteuerung mit new und override.
Neben den Zugriffsbezeichnern public, private und protected steht in C# der Zugriffsbezeichner internal zur Verfügung. Auf Mitglieder mit dem Zugriff internal kann von Klassen desselben Projekts aus, jedoch nicht von außerhalb des Projekts zugegriffen werden.
In Java werden Parameter immer nach Wert übergeben. C# ermöglicht mit dem Schlüsselwort ref das Übergeben von Parametern als Verweis. Dies ermöglicht der Mitgliedsfunktion, den Wert des Parameters zu ändern.
C# bietet darüber hinaus die Möglichkeit, Parameter mit Hilfe des out-Schlüsselwortes zu definieren, das genau wie ref funktioniert, abgesehen davon, dass die als Parameter übergebene Variable den Wert nicht vor dem Aufruf kennen muss.
Java verwendet die Methode GetClass(), um ein Class-Objekt mit Informationen zum aufgerufenen Objekt zurückzugeben. Das Type-Objekt ist das .NET-Äquivalent zum Class-Objekt und kann auf verschiedene Weise abgerufen werden:
| Durch Aufrufen der GetType()-Methode für eine Objektinstanz |
| Durch Verwenden des typeof-Operators für den Typennamen |
| Durch Ermitteln des Typs nach Name mit der Klasse System.Reflection |
Während Java-Schnittstellen Konstanten besitzen können, ist dies in C# nicht möglich. Bei der Implementierung von Schnittstellen stellt C# eine explizite Schnittstellenimplementierung bereit. Dies ermöglicht einer Klasse die Implementierung zweier Schnittstellen unterschiedlicher Quelle und gleichem Mitgliedsnamen. Die explizite Schnittstellenimplementierung kann auch dazu verwendet werden, Schnittstellenimplementierungen vor dem Benutzer zu verbergen. Weitere Informationen zu diesem Thema finden Sie in Kapitel 10, Schnittstellen.
In Java-Programmen werden Eigenschaften häufig durch das Deklarieren von get- und set-Methoden eingesetzt. In C# erscheint eine Eigenschaft dem Benutzer einer Klasse als Feld, bietet jedoch get- und set-Zugriffsroutinen zum Durchführen von Lese- oder Schreiboperationen.
Ein Indizierer ähnelt einer Eigenschaft, statt jedoch wie ein Feld auszusehen, wird der Indizierer dem Benutzer als Array angezeigt. Wie die Eigenschaften besitzen Indizierer get- und set-Zugriffsroutinen; im Gegensatz zu den Eigenscahften kann ein Indizierer jedoch für verschiedene Typen überladen werden. Dies ermöglicht das Indizieren von Datenbankzeilen nach Spaltenzahl und Spaltenname sowie das Indizieren von Hashtabellen nach Hashschlüssel.
Wenn ein Objekt in Java einen Rückruf benötigt, wird mit einer Schnittstelle angegeben, wie das Objekt gebildet wird, und eine Methode innerhalb der Schnittstelle wird für den Rückruf aufgerufen. Bei C#-Schnittstellen kann ein ähnlicher Ansatz verwendet werden.
C# stellt Zuweisungen bereit, die man sich wie typensichere Funktionszeiger vorstellen kann. Eine Klasse kann eine Zuweisung für eine Funktion der Klasse erstellen, anschließend kann die Zuweisung an eine Funktion übergeben werden, die diese Zuweisung akzeptiert. Anschließend kann die Funktion die Zuweisung aufrufen.
C# baut auf Zuweisungen mit Ereignissen auf, die von den .NET-Frameworks verwendet werden. Ereignisse implementieren das Veröffentlichen-Abonnieren-Prinzip; wenn ein Objekt (beispielsweise ein Steuerelement) ein Klickereignis unterstützt, kann eine beliebige Anzahl weiterer Klassen eine Zuweisung registrieren, die bei Auslösen des Ereignisses aufgerufen werden soll.
Attribute dienen der Weitergabe beschreibender Daten vom Programmierer an anderen Code. Bei diesem Code kann es sich um die Laufzeitumgebung, einen Designer, ein Tool zur Codeanalyse oder um ein benutzerdefiniertes Tool handeln. Attributinformationen werden über einen Vorgang abgerufen, der als Reflektion bezeichnet wird.
Attribute werden von eckigen Klammern umschlossen und können für Klassen, Mitglieder, Parameter und weitere Codeelemente gesetzt werden. Beispiel:
[CodeReview("1/1/199", Comment="Rockin'")] class Test { }
Die C#-Anweisungen werden dem Java-Programmierer bekannt vorkommen, es gibt jedoch einige neue Anweisungen und ein paar Unterschiede bei den vorhandenen Anweisungen zu beachten.
Die import-Anweisung wird in Java dazu eingesetzt, ein Paket zu ermitteln und die Typen in die aktuelle Datei zu importieren.
In C# wird diese Operation aufgeteilt. Die Assemblierungen, von denen ein Codeabschnitt abhängt, müssen explizit angegeben werden, entweder über die Befehlszeile mit Hilfe der Option /r oder in der Visual Studio-IDE. Die grundlegenden Systemfunktionen (aktuell die in mscorlib.dll enthaltenen Funktionen) sind die einzigen, die automatisch vom Compiler importiert werden.
Nachdem eine Assemblierung referenziert wurde, können die enthaltenen Typen verwendet werden, müssen jedoch unter Verwendung des vollqualifizierten Namens angegeben werden. Die reguläre Ausdrucksklasse heißt beispielsweise System.Text.RegularExpressions.Regex. Dieser Klassenname kann direkt verwendet werden, oder es werden mit Hilfe der using-Anweisung die Typen eines Namespaces in den Namespace oberster Ebene importiert. Mit der folgenden using-Klausel
using System.Text.RegularExpressions;
kann die Klasse einfach durch Einsatz von Regex angegeben werden. Es gibt außerdem eine Variante der using-Anweisung, die zur Vermeidung von Namenskollisionen das Angeben eines Typenalias ermöglicht.
Java kann weder bei Konvertierungen noch bei mathematischen Fehlern Überläufe ermitteln.
In C# kann eine solche Ermittlung durch die checked- und unchecked-Anweisungen und Operatoren gesteuert werden. Konvertierungen und mathematische Operationen, die in einem als checked deklarierten Kontext erfolgen, erzeugen Ausnahmen, wenn die Operation zu einem Überlauf oder Fehlern führt; die Ausführung einer solchen Operation in einem als unchecked deklarierten Kontext führt nie zu einer Fehlerausgabe. Der Standardkontext wird durch das Compilerflag /checked gesteuert.
Der so genannte unsichere Code in C# ermöglicht die Verwendung von Zeigervariablen und wird eingesetzt, wenn die Leistung extrem wichtig ist oder eine Integration mit vorhandener Software benötigt wird, beispielsweise mit COM-Objekten oder systemeigenem Code in DLLs. Die fixed-Anweisung wird dazu verwendet, ein Objekt »festzunageln«, damit es bei einer Speicherbereinigung nicht verschoben wird.
Da von der Laufzeit nicht geprüft werden kann, ob der unsichere Code gefahrlos ausgeführt werden kann, kann eine Ausführung nur erfolgen, wenn dem Code vom Laufzeitsystem vertraut wird. Dies verhindert eine Ausführung in Downloadszenarien.
Das C#-Zeichenfolgenobjekt kann für den Zugriff auf bestimmte Zeichen indiziert werden. Beim Zeichenfolgenvergleich werden nicht die Zeichenfolgenverweise, sondern die Zeichenfolgenwerte miteinander verglichen.
Zeichenfolgenliterale weisen in C# ebenfalls Unterschiede auf; C# unterstützt Escapezeichen innerhalb von Zeichenfolgen, die zum Einfügen von Sonderzeichen verwendet werden. Die Zeichenfolge \t wird beispielsweise in ein Tabulatorzeichen übersetzt.
Die XML-Dokumentation in C# ähnelt Javadoc, C# gibt jedoch nicht die Struktur der Dokumentation vor, und der Compiler prüft die Richtigkeit der Dokumentation und erzeugt eindeutige Bezeichner für Verknüpfungen.
Es gibt einige weitere Unterschiede:
| Der >>>-Operator ist in C# nicht vorhanden, da der >>-Operator ein verschiedenes Verhalten für Typen mit und ohne Vorzeichen aufweist. |
| Anstelle von instanceof wird der is-Operator verwendet. |
| Es ist keine benannte break-Anweisung vorhanden, diese wird durch goto ersetzt. |
| Die switch-Anweisung verbietet das »Durchfallen« von Code, switch kann für Zeichenfolgenvariablen eingesetzt werden. |
| Es ist nur eine Arraydeklarationssyntax verfügar: int[] arr. |
| C# ermöglicht bei Verwendung des params-Schlüsselwortes eine variable Anzahl Parameter. |
C# und Visual Basic 6 sind relativ unterschiedliche Sprachen. C# ist eine objektorientierte Sprache, Visual Basic 6 bietet nur beschränkte objektorientierte Funktionen. VB7 weist zusätzliche objektorientierte Funktionen auf, daher kann eine Lektüre der VB7-Dokumentation sehr aufschlussreich sein.
In Visual Basic enden Anweisungsblöcke auf eine Art von END-Anweisung, und es dürfen sich nicht mehrere Anweisungen in einer Zeile befinden. In C# werden Blöcke mit geschweiften Klammern ({}) gekennzeichnet, und die Position der Zeilenumbrüche spielt keine Rolle, da das Ende einer Anweisung mit einem Semikolon gekennzeichnet wird. Obwohl der nachfolgende Code vielleicht keinen guten Stil darstellt und hässlich zu lesen ist, ist er in C# möglich:
for (int j = 0; j < 10; j++) {if (j == 5) Func(j); else return;}
Diese Zeile trägt die gleiche Bedeutung wie der folgende Codeabschnitt:
for (int j = 0; j < 10; j++) { if (j == 5) Func(j); else return; }
Auf diese Weise wird der Programmierer zwar weniger eingeschränkt, es sind jedoch auch Abkommen bezüglich des Stils erforderlich.
Obwohl viele der in VB und C# verwendeten Datentypen übereinstimmen, gibt es einige wichtige Unterschiede, ein ähnlicher Name kann beispielsweise einen anderen Datentyp bezeichnen.
Der wichtigste Unterschied besteht darin, dass C# bei Variablendeklaration und -verwendung strikter ist. Alle Variablen müssen vor der Verwendung deklariert werden, und sie müssen mit einem bestimmten Typ deklariert werden – es ist kein Variant-Typ vorhanden, der einen beliebigen Typ enthalten kann1 .
Variablendeklarationen erfolgen einfach durch Einfügen des Typnamens vor der Variablen; es gibt keine dim-Anweisung.
Konvertierungen zwischen Typen werden in C# ebenfalls strenger gehandhabt als in Visual Basic. C# kennt zwei Arten der Konvertierung, die implizite und die explizite Konvertierung. Implizite Konvertierungen sind diejenigen, bei denen kein Datenverlust auftritt – d. h., der Quellwert passt stets in die Zielvariable. Beispiel:
int v = 55; long x = v;
Das Zuweisen von v zu x ist möglich, da int-Variablen immer in long-Variablen passen.
Explizite Konvertierungen dagegen sind Konvertierungen, bei denen ein Datenverlust auftreten kann bzw. die fehlschlagen können. Aufgrund dieser Tatsache muss die Konvertierung mit Hilfe einer Typumwandlung explizit angegeben werden:
long x = 55; int v = (int) x;
Obwohl die Konvertierung in diesem Fall sicher ist, kann long Zahlen enthalten, die zu groß sind, um in einen int-Wert zu passen, daher ist eine Typumwandlung erforderlich.
Wenn das Ermitteln eines Überlaufs während der Konvertierung von Bedeutung ist, kann mit der checked-Anweisung die Überlaufermittlung aktiviert werden. Weitere Informationen hierzu finden Sie in Kapitel 15, Konvertierungen.
In Visual Basic lauten die ganzzahligen Datentypen Integer und Long. In C# werden diese durch die Typen short und int ersetzt. Es ist ebenfalls ein long-Typ vorhanden, bei diesem handelt es sich jedoch um einen 64-Bit-Typ (8-Byte). Dies sollten Sie im Hinterkopf behalten, denn wenn Sie in C# dort Long einsetzen, wo Sie in Visual Basic long verwenden, werden die Programme sehr viel größer und langsamer. Byte dagegen kann fast mit byte gleichgesetzt werden.
C# verfügt des Weiteren über die Datentypen ushort, uint und ulong (ohne Vorzeichen) sowie den Typ sbyte, einen byte-Wert mit Vorzeichen. Diese sind in bestimmten Situationen nützlich, funktionieren jedoch nicht in allen weiteren .NET-Sprachen und sollten daher sparsam eingesetzt werden.
Die Gleitkommatypen Single und Double werden in float und double umbenannt, und der Boolean-Typ wird zu bool.
Viele der integrierten Funktionen von Visual Basic sind für C#-Zeichenfolgentypen nicht verfügbar. Es gibt Funktionen für das Suchen von Zeichenfolgen, das Extrahieren von Teilzeichenfolgen und das Durchführen weiterer Operationen. Siehe hierzu die Dokumentation des System.String-Typs.
Die Zeichenfolgenverkettung erfolgt nicht über den &-Operator, sondern über +.
In C# erhält das erste Element eines Arrays immer den Index 0, und es gibt keine Möglichkeit, höhere oder niedrigere Grenzen festzulegen oder ein redim für Arrays auszuführen. Über ArrayList im Namespace System.Collection wird jedoch eine Dimensionierung bereitgestellt, zusammen mit weiteren nützlichen Auflistungsklassen.
Die C#-Operatoren weisen gegenüber Visual Basic einige wenige Unterschiede auf, daher müssen Sie sich mit diesen besonders vertraut machen.
| VB-Operator | C#-Äquivalent |
| ^ | Keiner. Siehe Math.Pow() |
| Mod | % |
| & | + |
| = | == |
| <> | != |
| Like | Keiner. System.Text.RegularExpressions.Regex erledigt einige dieser Aufgaben, ist jedoch komplexer. |
| Is | Keiner. Der C#-Operator is trägt eine andere Bedeutung. |
| And | && |
| Or | || |
| Xor | ^ |
| Eqv | Keiner. A Eqv B entspricht !(A ^ B). |
| Imp | Keiner. |
Da C# eine objektorientierte Sprache ist2 , stellen Klassen die hauptsächliche Organisationseinheit dar; Code oder Variablen werden nicht in globalen Bereichen verwaltet, sondern immer mit einer spezifischen Klasse verknüpft. Dies führt zu Code, der recht anders als der Visual Basic-Code strukturiert und organisiert wird. Dennoch gibt es weiterhin Gemeinsamkeiten. Eigenschaften können weiterhin verwendet werden, auch wenn sie eine andere Syntax aufweisen und keine Standardeigenschaften vorhanden sind.
In C# müssen Funktionsparameter einen deklarierten Typ aufweisen, und anstelle von ByVal wird mit Hilfe von ref angegeben, dass der Wert einer übergebenen Variable bearbeitet werden kann. Die Funktion ParamArray kann durch Verwenden des params-Schlüsselwortes ausgeführt werden.
C# und Visual Basic verfügen über ähnliche Steuerungsstrukturen, die verwendete Syntax unterscheidet sich jedoch leicht.
In C# gibt es keine Then-Anweisung; nach der Bedingung folgt die Anweisung oder der Anweisungsblock, die/der bei erfüllter Bedingung ausgeführt werden soll. Im Anschluss an Anweisung oder Anweisungsblock kann eine optionale else-Anweisung vorliegen.
Der folgende Visual Basic-Code
If size < 60 Then value = 50 Else value = 55 order = 12 End If
if (size < 60) value = 50; else { value = 55; order = 12; }
In C# gibt es keine ElseIf-Anweisung.
Die Syntax von for-Schleifen ist in C# anders, das Konzept bleibt jedoch dasselbe, abgesehen davon, dass die am Ende einer Schleife durchgeführte Operation in C# explizit angegeben werden muss. Mit anderen Worten, der folgende Visual Basic-Code
For i = 1 To 100 ' Weiterer Code hier } kann umgeschrieben werden zu for (int i = 0; i < 10; i++) { // Weiterer Code hier }
C# unterstützt die For Each-Syntax über die foreach-Anweisung, die für Arrays, Auflistungsklassen und weitere Klassen eingesetzt werden kann, die eine geeignete Schnittstelle offen legen.
C# weist zwei Schleifenkonstruktionen aus, die das Do Loop ersetzen. Die while-Anweisung wird zum Durchlaufen einer Schleife verwendet, während eine Bedingung erfüllt ist, do while arbeitet auf die gleiche Weise, abgesehen davon, dass auch ein Schleifendurchlauf vollzogen wird, wenn die Bedingung nicht erfüllt ist. Der folgende Visual Basic-Code
I = 1 fact = 1 Do While I <= n fact = fact * I I = I + 1 Loop
kann folgendermaßen umgeschrieben werden:
int I = 1; int fact = 1; while (I <= n) { fact = fact * I; I++; }
Eine Schleife kann mit Hilfe der break-Anweisung verlassen oder im nächsten Durchlauf mit der continue-Anweisung fortgesetzt werden.
Die switch-Anweisung in C# führt die gleiche Aufgabe aus wie Select Case. Dieser VB-Code
Select Case x Case 1 Func1 Case 2 Func2 Case 3 Func2 Case Else Func3 End Select
kann folgendermaßen umgeschrieben werden:
switch (x) { case 1: Func1(); break; case 2: case 3: Func2(); break; default: Func3(); break; }
In C# gibt es keine On Error-Anweisung. Fehlerbedingungen in .NET werden über Ausnahmen gehandhabt. Weitere Informationen zu diesem Thema finden Sie in Kapitel 4, Ausnahmebehandlung.
In C# sind weder With, Choose noch ein Äquivalent zu Switch verfügbar. Des Weiteren kann auch nicht auf die CallByName-Funktion zurückgegriffen werden, auch wenn diese Operation über die Reflektion ausgeführt werden kann.
Visual C++ und Visual Basic wurden beide zur Verwendung in der .NET-Welt erweitert.
In der Visual C++-Welt wurde der Sprache ein Satz »verwalteter Erweiterungen« hinzugefügt, um den Programmierern das Erzeugen und Verwenden von Komponenten für die Common Language Runtime zu ermöglichen. Das Visual C++-Modell stattet den Programmierer mit umfangreicheren Steuerungsmöglichkeiten aus als das C#-Modell, da sowohl verwaltete (Speicherbereinigung) als auch nicht verwaltete Objekte (new und delete) geschrieben werden können.
Eine .NET-Komponente wird durch das Verwenden von Schlüsselworten zum Bearbeiten der Bedeutung vorhandener C++-Konstruktionen erstellt. Wenn beispielsweise das Schlüsselwort __gc einer Klassendefinition vorangestellt wird, ermöglicht dieses Vorgehen die Erstellung einer verwalteten Klasse und verbietet der Klasse die Verwendung von Konstruktionen, die in der .NET-Umgebung nicht ausgedrückt werden können (beispielsweise die Mehrfachvererbung). Von den verwalteten Erweiterungen aus können auch die .NET-Systemklassen verwendet werden.
Visual Basic hat ebenfalls erhebliche Verbesserungen erfahren. Es werden nun objektorientierte Konzepte wie Vererbung, Kapselung und Überladung unterstützt, damit eine nahtlose Integration in die .NET-Umgebung gewährleistet ist.
1 Der Typ object kann einen beliebigen Typ enthalten, es ist jedoch bekannt, welcher Typ enthalten ist.
2 Siehe hierzu Kapitel 1, Grundlagen der objektorientierten Programmierung.
| << zurück |
| |||||
| |||||
| |||||
| |||||
| |||||
| |||||
| |||||
Copyright © Galileo Press GmbH 2001 - 2002
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.