Von VB(A) zu C# - Stolpersteine vermeiden

Stand: Dezember 2004, überarbeitet September 2007

Der folgende Spickzettel bezieht sich auf das »Umsetzen« von Quellcode von VB(A) zu C#, wodurch er auch entstanden ist. Vorgehensweise: »Paste and Copy« von Editorfenster zu Editorfenster und anschließendes schrittweises Ersetzen in C# Code.

Es kann hilfreich sein, sich vorab im VB(A) Code einige Notizen zu machen oder Abschnitte mit einem Kommentarhinweis zu kennzeichnen. Beim späteren Umschreiben überliest man aus Gewohnheit doch das eine oder andere und vergisst, es zu ersetzen. Mit der folgenden Punkteliste kann man sich somit ein paar Fehlermeldungen ersparen. Oder, was schlimmer ist, die ausbleibende Fehlermeldung...

Seitenanfang

Spickzettel - Syntaxunterschiede

Die aufgezählten Punkte der Liste bezeichnen (meistens) nur den VB(A) Syntax und nicht den Lösungsansatz beziehungsweise das Äquivalent in C#. Ausnahmen hiervon sind am Ende der Liste angefügt.

  1. Variablen und Felder
    1. Deklaration und Dimensionierung, Gültigkeitsbereiche
    2. Groß- und Kleinschreibung, Stichpunkt: »Case Sensitive«
    3. Verwendung von Schlüsselwörtern, Stichpunkt: Let und Set
    4. Objectvariablen
    5. Array:
      • Dim arr(10) As Integer deklariert ein Array mit 11 Elementen, von 0 bis 10
      • Redim und Redim Preserve kein Äquivalent, aus Performancegründen ist das auch gut so, Stichpunkt: ArrayLists
    6. Choose-Funktion kein Äquivalent
    7. Switch-Funktion kein Äquivalent
  2. Konstanten und Enumaration
  3. Datentypen
    1. Unterschiede COM und CTS
    2. Datentypen vorab auf implizite und explizite Konvertierung überprüfen
    3. Datentyp Variant und »Untertype«
    4. Datentyp Boolean: False Wert 0, True Wert -1
  4. Operatoren
    1. Zuweisungen, Wertprüfungen und Zustände - Äquivalenzen überprüfen
    2. Zeichenfolgenverkettung: & Operator
    3. Schlüsselwörter Like, Is, Nothing
    4. Logische und Bit Operatoren
      • Kein Potenz ^ (Circumflex)-Operator in C#: Wenn 2^8 nicht mehr 256 sondern 10 ist. *Huch*
      • Zu Eqv und Imp gibt es in C# kein Äquivalent. Wer`s jemals benutzt hat, hier ist ein Beispiel zu einer Ersatzkonstruktion
  5. Blöcke und Kontrollstrukturen
    1. Generelles Beenden, Begrenzen von Verzweigungen und Schleifen
    2. With-Anweisung kein Äquivalent
  6. Prozeduren
    1. Deklaration Anweisungen Function, Sub, Property
    2. Gültigkeitsbereiche Public, Private, Friend, Static
    3. Eigenschaften Unterscheidung Property Get, Property Let(primitive Datentypen) und Property Set(Objekte)
    4. Keine CallByName-Funktion vorhanden
    5. Parameterübergabe
      • byVal (ByValue) und byRef (ByReference), optionale Parameter
  7. Frühes und spätes Binden von Objekten, Schwerpunkt Automation
  8. Events (Ereignisse)
  9. Fehlerbehandlung On Error

Seitenanfang

Schlüsselwort Me

Me in VB(A) entspricht nicht this in C#!

In VB(A) verhält sich Me wie eine implizit deklarierte Variable. Bei Verwendung in einem Klassenmodul steht Me allen Prozeduren zu Verfügung. Weiter stellt Me eine Möglichkeit dar, sich auf eine von mehreren Instanzen einer Klasse zu beziehen, in der aktuell der Code ausgeführt wird.

In VB.NET stellt Me ein Bezug auf die eigene Klasseninstanz dar. In C# entspricht dies dem Schlüsselwort this.

Gültigkeitsbereiche und Lebensdauer (von was und für wen eigentlich?)

Nichts kann so verwirrend sein wie das Deklarieren in VB(A). Dim, New, WithEvents aber nur ohne New und anders rum. Die Anweisung Static und/oder das Schlüsselwort Static. »Deklaratoren« für Variablen aber nicht Konstanten, »Modifikatoren« für »Deklarationen«, Typen und Prozeduren und ja auch für Konstanten *g*. Nicht mehr gültige Modifikatoren, die aber »abwärtskompatibel«, wie wir das von MS gewöhnt sind, noch funktionieren und so weiter.

Wer denkt, daß er dieses Thema jemals richtig in VB(A) durchschaut hat, klopft sich jetzt auf die Schulter :p. Allen Anderen sei dieser Link empfohlen Gültigkeitsbereiche.

Sicher wissen wir^^: Wenn Variablen mit Dim auf Prozedurebene (ohne Static Deklaration), also »lokal« deklariert wurden, sind sie ab der Zeile, die die Deklaration enthält, bis zum Ende der Prozedur gültig.

In C# ergeben sich die Gültigkeitsbereiche eindeutig aus der durch die geschweiften Klammern eingegrenzte Blockstruktur.

Methoden und Klassendefinition

C# kennt nur Methoden mit und ohne (void) Rückgabewert.

In VB(A) entspricht dies, ungefähr, den Function- und Sub-Prozeduren.

Bei Methoden in C# steht der Datentyp des Rückgabewertes vorne, gefolgt vom Namen und der Parameterliste

public double anyMethod(double value1, double value2) { ... - Nochmal ByVal|ByRef : Die Parameter sind standardmäßig auf ByVal gesetzt. Um eine Parameterübergabe By Reference zu erzwingen, muss das Schlüsselwort ref verwendet werden.

Property- Prozeduren in VB(A), können für eine Eigenschaft unterschiedliche Zugriffsebenen deklarieren. Public Property Get - Private Property Let|Set -> in C# müssen beide, Get und Set, die gleiche Zugriffsebene besitzen.


   'VB(A) Class clsPath
   Private sPath As String

   Public Property Get pPath() As String
      pPath = sPath
   End Property

   Private Property Let pPath(ByVal Value As String)  
      sPath = Value 'aus einer Prozedur, innerhalb des Klassenmoduls
   End Property
   ...
   
   'Objekt erzeugen
   Private oPath as clsPath
   ...
   If IsObjectNothing(oPath) Then Set oPath = New clsPath
   
   oPath.pPath = 'irgendein Pfad
   
   // C#
   public class CPath {
      private string path;
      ...
      public string Path {
         get
         {return path;}
         set
         {path = value;}
      {
      ...
   {

   // Objekt erzeugen
   private CPath myPath = new CPath("irgendein Pfad");
   

Seitenanfang

Nochmal Array

Dimensionierung:


   Dim arr(10) As Integer 'VB(A)

   int[]arr = new int[11]; // C#

Redim und ReDim Preserve existieren nicht in C#. Ein möglicher Workaround wäre:


   'VB(A)
   Dim arr() As Integer, i As Integer
   ...
   ReDim Preserve arr(i)

   // C#
   int[] arr;
   int i;
   ...
   int[] arrCopy = new int[i + 1];
   if (arr != null)
      Array.Copy(arr, arrCopy, Math.Min(arr.Length, arrCopy.Length));
   arr = arrCopy;

Aber die bessere Lösung ist ArrayList. Ab >= C# 2005 bietet sich auch die Array.Resize-Methode an.

Nochmal Blöcke

With-Anweisung:


   'VB(A)
   With IrgendeineKlasse
      .EineEigenschaft = EinWert
      .NochEineEigenschaft = EinWert
      .EineAndereEigenschaft = EinWert
      .EineMethode(ArgListe)      
   End With

   // C#
   IrgendeineKlasse.EineEigenschaft = EinWert;
   IrgendeineKlasse.NochEineEigenschaft = EinWert;
   IrgendeineKlasse.EineAndereEigenschaft = EinWert;
   IrgendeineKlasse.EineMethode(ArgListe);
   

Püh? ehm...

Seitenanfang

Tabellarischer Vergleich der Operatoren in VB(A), VB und C#

Arithmetische Operatoren
Art VBA VB.NET C# Information
Tabelle 1 - Arithmetische Operatoren: VB(A) · VB · C#
Potenzoperator ^ ^ Kein benutze in VB und C# Math.Pow
+ - * /  + - * /  + - * /  Grundrechnungsarten
Vorzeichenoperator - - - beschreibt eine negative Zahl (-x)
Vorzeichenoperator Kein Kein + beschreibt eine positive Zahl (+x)
Divisionsoperator \ \ Kein liefert den ganzzahligen Anteil der Division (x\y)
Restwertoperator Mod Mod % liefert den Restwert einer ganzzahligen Division (x Mod y)
Dekrementoperator Kein Kein -- Dekrement. Verringert den Inhalt des Operanden um 1.
(--i) liefert den Wert eines Operanden nach einer Verringerung.
(i--) liefert den Wert eines Operanden vor der Verringerung
Inkrementoperator Kein Kein ++ Inkrement. Erhöht den Inhalt des Operanden um 1.
(++i) liefert den Wert eines Operanden nach der Erhöhung.
(i++) liefert den Wert eines Operanden vor der Erhöhung

Seitenanfang

Vergleichende Operatoren
Art VBA VB.NET C# Information
Tabelle 2 - Vergleichsoperatoren: VB(A) · VB · C#
Kleiner als < < < True wenn, Ausdruck1 < Ausdruck2
Kleiner oder gleich <= <= <= True wenn, Ausdruck1 <= Ausdruck2
Größer als > > > True wenn, Ausdruck1 > Ausdruck2
Größer oder gleich >= >= >= True wenn, Ausdruck1 >= Ausdruck2
Gleich = = == True wenn, Ausdruck1 = Ausdruck2
Ungleich <> <> != True wenn, Ausdruck1 <> Ausdruck2
Verweisvariablen Is Is Kein True wenn, Objekt1 Is Objekt2
In C# wird mit dem is-Operator ermittelt, ob ein Objektverweis in einen Typ oder eine Schnittstelle konvertiert werden kann, beziehungsweise ob eine bestimmte Schnittstelle unterstützt wird. Siehe auch Sonstige Operatoren TypeOf...Is. Ein äquivalenter Operator für VB(A)`s Is wäre in C# der ==-Operator
Verweisvariablen Kein IsNot Kein True wenn, Objekt1 nicht gleich Objekt2 ist. >= VB 2005
Zeichenfolge Like Like Kein True wenn, Zeichenfolge Like Muster.
mögliche Platzhalterzeichen: ?, *, #, [ZeichenListe], [!ZeichenListe]

Seitenanfang

Logische Operatoren
Art VBA VB.NET C# Information
Tabelle 3 - Logische Operatoren: VB(A) · VB · C#
1.1 And-Operator And And & True wenn, Ausdruck1 und Ausdruck2 True ist. Es werden immer beide Ausdrücke ausgewertet
1.2 And-Operator, Kurzschlussoperator Kein AndAlso && True wenn, Ausdruck1 True ist und Ausdruck2 True ist. Ausdruck2 wird nur dann geprüft, wenn Ausdruck1 True ist
2.1 Or-Operator Or And | True wenn, Ausdruck1 oder Ausdruck2 True ist
2.2 Or-Operator, Kurzschlussoperator Kein OrElse || True wenn, Ausdruck1 True ist oder Ausdruck2 True ist. Ist Ausdruck1 bereits True wird Ausdruck2 nicht mehr ausgewertet
XOR-Operator XOR XOR ^ True wenn, Ausdruck1 und Ausdruck2 unterschiedliche Wahrheitswerte besitzen
Negationsoperator Not Not ! Kehrt einen Wahrheitswert um
logische Äquivalenz Eqv Kein Kein Dient dazu, zwei Ausdrücke mit einer logischen Äquivalenzoperation zu verknüpfen.
Ausdruck1 Eqv Ausdruck2 entspricht in VB Not (Ausdruck1 Xor Ausdruck2), welches ein gegenteiliges Xor darstellt, oder einem bitweisen Vergleich Ausdruck1 = Ausdruck2. Dementsprechend kann in C# !(Ausdruck1 ^ Ausdruck2), Ausdruck1 == Ausdruck2 benutzt werden.
logische Implikation Imp Kein Kein Dient dazu, 2 Ausdrücke mit einer logischen Implikationsoperation zu verknüpfen.
Ausdruck1 Imp Ausdruck2 entspricht in VB (Not Ausdruck1) Or Ausdruck2. Dementsprechend kann in C# !(x) | y benutzt werden.
Bedingungsprüfung Kein IsFalse Kein Der IsFalse-Operator bestimmt, ob ein Ausdruck False ist. Wenn dieser Operator verwendet wird, muss auch der IsTrue-Operator definiert werden.
Bedingungsprüfung Kein IsTrue Kein Der IsTrue-Operator bestimmt, ob ein Ausdruck True ist. Wenn dieser Operator verwendet wird, muss auch der IsFalse-Operator definiert werden.

Nochmal Eqv-Operator und Imp-Operator, umgebaut für VB und C#, (hier gehts weiter zu Bitweise Operatoren).


   'VB(A)
   Private Sub Sequence()
      Debug.Print bEqv(3 > 2, 2 > 1) 'Liefert True
      Debug.Print bEqv(2 > 3, 2 > 1) 'Liefert False
      Debug.Print bEqv(2 > 3, 1 > 2) 'Liefert True
      Debug.Print
      Debug.Print bImp(3 > 2, 2 > 1) 'Liefert True
      Debug.Print bImp(3 > 2, 1 > 2) 'Liefert False
      Debug.Print bImp(2 > 3, 1 > 2) 'Liefert True      
   End Sub
   Public Function bEqv(byVal x As Boolean, byVal y As Boolean) As Boolean
      bEqv = x Eqv y 'alternativ, gegenteiliges »XOR« bEqv = Not (x Xor y) 
                     'oder bitweiser Vergleich bEqv = (x = y) 
   End Function   
   Public Function bImp(byVal x As Boolean, byVal y As Boolean) As Boolean
      bImp = x Imp y 'alternativ bImp = (Not x) Or y
   End Function
   
   'VB
   Sub Main()
      Console.WriteLine(Eqv(3 > 2, 2 > 1))
      Console.WriteLine(Eqv(3 > 3, 2 > 1))
      Console.WriteLine(Eqv(2 > 3, 1 > 2))
      Console.WriteLine
      Console.WriteLine(Imp(3 > 2, 2 > 1))
      Console.WriteLine(Imp(3 > 2, 1 > 2))
      Console.WriteLine(Imp(2 > 3, 1 > 2))
   End Sub
   Public Function Eqv(ByVal x As Boolean, ByVal y As Boolean) As Boolean
      Return Not (x Xor y) 'x = y
   End Function
   Public Function Imp(ByVal x As Boolean, ByVal y As Boolean) As Boolean
      Return (Not x) Or y
   End Function
   
   // C#  
   class MyClass {
      public static void Main(string[] args) {
         Console.WriteLine(Eqv(3 > 2, 2 > 1));
         Console.WriteLine(Eqv(2 > 3, 2 > 1));
         Console.WriteLine(Eqv(2 > 3, 1 > 2));
         Console.WriteLine();
         Console.WriteLine(Imp(3 > 2, 2 > 1));
         Console.WriteLine(Imp(3 > 2, 1 > 2));
         Console.WriteLine(Imp(2 > 3, 1 > 2));
      }
      public static bool Eqv(bool x, bool y) {
         return !(x ^ y); // x == y;
      }
      public static bool Imp(bool x, bool y) {
         return !(x) | y;
      }
   }
   

Seitenanfang

Bitweise Operatoren
Art VBA VB.NET C# Information
Tabelle 4 - Bitweise Operatoren: VB(A) · VB · C#
And-Operator And And &

Ausdruck 3 -> Binär 00000011 
Ausdruck 9 -> Binär 00001001 
Ergebnis 1 -> Binär 00000001
inklusiver Or-Operator Or Or |

Ausdruck 3  -> Binär 00000011 
Ausdruck 9  -> Binär 00001001 
Ergebnis 11 -> Binär 00001011
exklusiver Or-Operator Xor Xor ^

Ausdruck 3  -> Binär 00000011
Ausdruck 9  -> Binär 00001001
Ergebnis 10 -> Binär 00001010
Einerkomplement Not Not ~ Invertiert jedes Bit eines Ausdrucks

Seitenanfang

Bit Verschiebung
Art VBA VB.NET C# Information
Tabelle 5 - Bit Verschiebung: VB(A) · VB · C#
nach links schieben Kein << <<

'Um 3 Stellen nach links verschieben 
Ausdruck << 3
Ausdruck 9  -> Binär 00001001
Ergebnis 72 -> Binär 01001000
nach rechts schieben Kein >> >>

'Um 3 Stellen nach rechts verschieben 
Ausdruck >> 3
Ausdruck 72 -> Binär 01001000
Ergebnis 9  -> Binär 00001001
Bemerkungen: Bei Bit Verschiebungen (links und rechts) werden die frei werdenden Leerstellen mit 0 Bits aufgefüllt. VB kann nach wie vor »Binärzahlen« nicht direkt verarbeiten. Um Binärzahlen darzustellen kann man einen String-Datentyp benutzen. »Zyklische« Verschiebungen werden ebenfalls in VB nicht unterstützt.

Seitenanfang

Verknüpfung
Art VBA VB.NET C# Information
Tabelle 6 - Verknüpfungen von Zeichenketten: VB(A) · VB · C#
1. Stringverkettung + + + Der + Operator verknüpft dann Zeichenketten miteinander wenn einer der beteiligten Operanden vom Typ string ist. Es erfolgt somit ein Stringverkettung und keine Addition. In C# werden weitere Operanden die nicht vom Typ string sind implizit in einen string konvertiert. Grundsätzlich können auch in VB(A) und VB Zeichenketten mit dem + verkettet werden. Ist jedoch einer der Operanden vom Typ Zahl führt dies zu einer Fehlermeldung.
2. Zeichenverkettung & & Kein Der & Operator funktioniert in VB(A) und VB wie der + Operator in C#. Er verknüpft Datentypen zu Zeichenketten. Operanden die nicht vom Typ string sind werden automatisch in einen String konvertiert

Seitenanfang

Zuweisende Operatoren
Art VBA VB.NET C# Information
Tabelle 7 - Zuweisungsoperatoren: VB(A) · VB · C#
Einfache Zuweisung = = = x=3 y=x y ->3
Parameter Zuweisung := := Kein Einem benannten Parameter einen Wert zuweisen
Komplexe Zuweisungen Komplexe Zuweisungsoperatoren zeigen mit verkürzter Schreibweise Anweisungen an. Hierbei ist der linke Operand auch immer der Ergebnisempfänger
Potenzierung Kein ^= Kein x=3 y=3 x^=y x ->27
Addition Kein += += x=3 y=3 x+=y x ->6
Subtraktion Kein -= -= x=3 y=3 x-=y x ->0
Multiplikation Kein *= *= x=3 y=3 x*=y x ->9
Division Kein /= /= x=3 y=3 x/=y x ->1
Division ganzer Zahlen Kein \= Kein x=4 y=3 x/=y x ->1
Modulodivision Kein Kein %= x=4 y=3 x%=y x ->1
Zeichenverkettung Kein &= += Stringausdrücke miteinander verknüpfen.
Bitweises And Kein Kein &= x=true y=false x&=y x ->false
Bitweises inklusives Or Kein Kein |= x=true y=false x|=y x ->true
Bitweises exklusives Or Kein Kein ^= x=true y=true x^=y x ->false
BitL(eft)-Shift Kein <<= <<= x=9 y=3 x<<=y x ->72
BitR(ight)-Shift Kein >>= >>= x=72 y=3 x>>=y x ->9
Null Coalesce Kein Kein ?? Der ?? Operator gibt den linken Operanden zurück, falls dieser nicht NULL ist. Andernfalls wird der rechte Operand zurückgegeben.

Seitenanfang

Sonstige Operatoren
Art VBA VB.NET C# Information
Tabelle 8 - Sonstige Operatoren: VB(A) · VB · C#
Punktoperator . | ! . | !* . Memberauswahl, Zugriff auf die Eigenschaften und Methoden einer Klasse.
Bemerkungen: *Laut MS Operatorenlisten wird das »!« immer noch in VB verwendet, allerdings fehlt mir der Code äh Glaube...
In VBA MS OFFICE 200x Access gilt? weiterhin die Regel der Trennung von ».« und »!«. Vor benutzerdefinierten Objekte ( Forms, Controls und so weiter) gehört das »!«. Von »Access« vorgegebene Auflistungen, Eigenschaften, Methoden, gehört der ».«. Zugriffe auf Prozeduren (Property, Function, Sub) von Klassenmodulen, Zuweisungen innerhalb von With-Blöcken, selbstdefinierten Typen und Felder benötigen ebenfalls die »Punktnotation«
Typenoperator Kein GetType() typeof liefert die Type eines Objekts. Die GetType-Methode liefert den Typ einer aktuell vorhandenen Instanz
Vergleichsoperator TypeOf...Is TypeOf...Is is True wenn, ein Objekt den zu prüfenden Typ entspricht. TypeOf objectname Is objecttype auf einen bestimmten Typen. In VB kann auch eine Prüfung daraufhin erfolgen, ob eine Schnittstelle unterstützt wird (check for interface implementation). Das Äquivalent hierzu von C# ist der is-Operator. Dieser ermittelt, ob ein Objektverweis in einen Typ oder eine Schnittstelle konvertiert werden kann, beziehungsweise ob eine bestimmte Schnittstelle unterstützt wird.
Konvertierung Kein Kein as as arbeitet ähnlich wie is. Es wird jedoch nicht nur eine Typen- und Schnittstellenprüfung durchgeführt, sondern auch eine gleichzeitige Konvertierung in einen Typ oder eine Schnittstelle. Kann ein Objekt nicht konvertiert werden, gibt as null zurück. Bei der Konvertierung zwischen kompatiblen Verweistypen ist der Einsatz von as effizienter, als die Verwendung von is. Bei der Verwendung des is-Operators müssen zwei Prüfungen erfolgen. Einmal bei Verwendung des Operators und ein zweitesmal bei der Konvertierung.
Funktionszeiger AddressOf AddressOf Kein In VB(A) wird der AddressOf-Operator verwendet, um die Speicheradresse einer Prozedur an eine API-Prozedur zu übergeben, die einen Funktionszeiger als Argument annimmt. In VB muss der AddressOf-Operator mit einem Delegate verwendet werden. Anstelle von Funktionszeigern arbeitet C# grundsätzlich mit »Delegaten«. Diese werden als Ersatz für einen Funktionszeiger beim Aufrufen von API-Prozeduren benutzt
Bedingte Prüfung IIf() IIf() ?: Einen von zwei Werten in Abhängigkeit eines dritten Wertes überprüfen. Entspricht in VB(A) und Vb der IIF() Funktion.

Seitenanfang