Workshop C# für Umsteiger

Willkommen bei unserem Workshop für Umsteiger auf C# – ausgeschrieben „C Sharp“ ausgesprochen „See Sharp“. Die folgenden Teile werden allen, die schon ein wenig Erfahrung mit Programmiersprachen haben zu einem Einstieg in die Sprache verhelfen.

Einführung

Manchmal muss es wehtun, damit es wirkt. Gerade wer von Sprachen wie Visual Basic kommt oder seinen Lebensunterhalt bislang mit Perl und PHP verdient hat, findet viele bittere Pillen in C#. Dieser Kurs versüßt den Umstieg auf die neue Sprache.

In diesem noch auf der Beta 2 von Visual Studio .NET basierenden Einsteigerkurs lernen Sie schon einige Besonderheiten von C# kennen. Gleich am Anfang nehmen Sie die erste Hürde und setzen sich mit der Deklaration von Datentypen auseinander. Denn die schönen Zeiten von Datentypen wie „Variant“ sind in C# vorbei. Sie können nicht einfach eine Variable deklarieren und ihr dann wahlweise einen String, eine Ganzzahl oder einen Fließkommawert zuweisen.

Das erscheint anfangs lästig. Doch denken Sie ein Mal daran, wie oft Sie schon verzweifelt Ihren Code auseinander genommen haben, nur um nach Stunden zu merken, dass eine Variable einen String enthält, die eigentlich eine Fließkommazahl enthalten sollte. Und denken Sie an den verzweifelten Blick Ihres Kollegen, der Ihren Code lesen muss und sich fragt, welche Daten die von Ihnen deklarierte Variable denn nun mit sich trägt.

Also muss eine Variable immer mit dem zugehörigen Typen deklariert werden. Achtung: Das funktioniert nicht mit „Dim“. Statt dessen wird die Variable mit voangestelltem Datentyp initialisiert. Für den Anfang sind die wichtigsten:

string varName;

definiert eine Variable, die einen Text enthält.

int varName;

deklariert eine Variable mit einer Ganzzahl (sprich, eine Zahl ohne Nachkommastellen).

double varName;

definiert eine Fließkommazahl mit 15 bis 16 Nachkommastellen.

Um dennoch zwischen den Variablentypen umzuschalten gibt es die Methode „ConvertTo“.

Ein kleines Beispiel als Trockenübung:

// Eine Zahl als String definieren

string stest = "12";

// in einen int umwandeln

int itest = Convert.ToInt16(stest);

// itest hat den Inhalt von stest erhalten, der zuvor in einen int verwandelt wurde

Hier wird der String „stest“ in einen 16 Bit langen Integer umgewandelt. Dieses Beispiel müssen Sie nicht eintippen — sie werden in den folgenden Listings immer wieder auf die Typenkonvertierung stoßen.

Um alles noch sicherer — und unbequemer — zu machen, unterscheidet C# zwischen Groß- und Kleinschreibung. Die Variable

int Test;

ist eine ganz andere als

int test;

Sobald Sie eine Variable in der falschen Schreibweise ansprechen, wird sich der Compiler beschweren.

Was gibt es noch besonderes an C#? Klar, die Strichpunkte. Gewöhnen Sie sich an, hinter jede Zeile einen Strichpunkt zu schreiben. Doch halt – nicht hinter jede Zeile: Sobald auf eine Anweisung ein mit geschweiften Klammern eingeschlossener Block folgt, darf kein Strichpunkt stehen, also:

//Mit Strichpunkt

int itest = Convert.ToInt16(stest);

aber

//Ohne Strichpunkt

if (itest == 12)

{

// Wieder mit Strichpunkt

MessageBox.Show("Passt.");

}

Und damit hätten wir eine weitere Besonderheit von C# geklärt: Mit den geschweiften Klammern fassen Sie Code-Blöcke zusammen, die zu einer Funktion, einer Schleife oder wie hier gezeigt einer IF-Anweisung gehören.

Das mag alles profan klingen — Strichpunkte wird wohl jeder hin bekommen. Aber glauben Sie mir: Selbst nach Jahren verderben noch vergessene Strichpunkte den Abend. Besonders bei Programm-Schnellschüssen, dem Utility zwischendurch, bremsen die fehlenden Strichpunkte. Denn weil ich so überzeugt bin, nie Strichpunkte zu vergessen, suche ich diesen Fehler gar nicht erst…

Die Klasse füllen

Nun gilt es, die Klasse mit Leben zu füllen. Los geht es mit der Definition einer internen Variablen. Die gilt nur innerhalb des Objektes, gehört als „private“ gleichsam zur Privatspähre, da sie von außen nicht zu sehen ist.

„myWert“ ist eine Variable vom Typ „double“, also eine Fließkommazahl von doppelter Genauigkeit. Fügen Sie die Variablendefinition direkt unterhalb der Klassendefinition ein:

private double myWert;

Weiter geht es gleich nach dem Konstruktor mit diesen Zeilen:

public double Wert

{

set

{

myWert = value;

}

get

{

return myWert;

}

}

„Wert“ ist noch eine Variable. Diesmal steht sie allen offen, die sie benutzen wollen, sie ist „public“ und vom Typ „double“. Die folgenden Zeilen legen das Verhalten fest, das die Variable an den Tag legt, sobald ihr eine Zahl zugewiesen wird (set) und wenn ihr Wert erfragt wird (get). Damit schaffen Sie eine klar definierte Schnittstelle zwischen Ihrem Objekt und der Außenwelt.

Alle internen Variablen bleiben im Objekt und kommunizieren nur über diese Schnittstelle mit der Außenwelt.

Bleiben noch zwei Methoden für unser Euro-Objekt. Eine heißt „toDM()“. Das „void“ davor bedeutet: Die Methode besitzt keinen Rückgabewert. Vielmehr belegt sie die Variable „myWert“ mit dem Ergebnis einer simplen Rechnung. Genauso verhält sich die Funktion „toEuro“.

public void toDM()

{

myWert = myWert * 1.95583;

}

public void toEuro()

{

myWert = myWert / 1.95583;

}

Damit ist unsere Euro-Klasse schon fertig. Jetzt müssen wir uns nur noch um Code kümmern, der diese Klasse auch nutzt. Der Übersicht halber sehen Sie vorher noch ein Mal die komplette Klasse classEuro:

using System;

namespace Csharp1

{

///

/// Enthält alles für die Euro-Umrechnung

///

public class classEuro

{

private double myWert;

 

public classEuro()

{

//

// TODO: Add constructor logic here

//

}

public double Wert

{

set

{

myWert = value;

}

get

{

return myWert;

}

}

public void toDM()

{

myWert = myWert * 1.95583;

}

 

public void toEuro()

{

myWert = myWert / 1.95583;

}

}

}

Das erste Programm

Genug geplaudert. Es geht an die Arbeit. Wenn Sie einen langsamen Rechner der Pentium-III-700er-Klasse haben, starten sie jetzt schon mal Visual Studio.NET. Bis zum Ende dieses Absatzes wird die IDE hoffentlich geladen sein.

Über das „Hallo Welt“ sind wir alle schon hinaus. Wir gehen mit C# gleich ran und programmieren etwas ähnlich Sinnfreies: Einen Euro-Umrechner für Windows.

Der hat viele Vorteile: Anhand des kleinen Programms erfahren Sie, wie man ein Objekt aufbaut und darin Variablen initialisiert. Außerdem kümmern wir uns um das Abfangen von Fehlermeldungen und die Konvertierung von

Variablentypen.

So, Visual Studio .NET sollte inzwischen geladen sein. Starten Sie ein neues Visual C#-Projekt, nehmen Sie die Vorlage „Windows Application“ und nennen Sie das Ganze „Csharp1“.

Nach kurzer Aufbauzeit sehen Sie das Standardformular. Das lassen Sie aber vorerst beiseite und bauen ein Euro-Objekt.

Eine neue Klasse bauen

Dazu klicken Sie rechts im Fenster „ClassView“ mit der rechten Maustaste auf den Programmnamen und wählen „Add – Add Class“. Geben Sie unter „Class Name“ die Bezeichnung „classEuro“ ein. Das vorangestellte „class“ soll Ihnen helfen, sich später zurecht zu finden und die Klasse als solche zu erkennen. Falls Ihnen das voangestellte „class“ zu lang ist, können Sie auch „cEuro“ oder „CEuro“ schreiben.

Nach einem Klick auf „Finish“ baut Visual Studio.NET das Grundgerüst der neuen Klasse auf:

using System;

namespace Csharp1

{

///

///

///

public class classEuro

{

public classEuro()

{

//

// TODO: Add constructor logic here

//

}

}

}

Die Entwicklungsumgebung spart Ihnen hier schon eine Menge Tipparbeit. „using System;“ bindet alle Klassen aus dem Namespace „System“ ein. Klingt gut? Zu Deutsch: Damit verschaffen Sie sich Zugriff auf alle Klassen, die unter „System“ zusammen gefasst sind. Dabei handelt es sich um grundlegende Klassen, etwa für die Ein- und Ausgabe oder mathematische Funktionen.

In den nachfolgenden Kommentarzeilen können Sie zwischen den XML-Tags „“ und „“ eine kurze Zusammenfassung schreiben, wozu die Klasse gut ist und was sie überhaupt macht. In diesem Beispiel ist das noch nicht nötig. Aber wenn Sie mit größeren Projekten los legen, sollten Sie dieses Kommentarangebot nutzen.

Danach folgt der Konstruktor. Das ist eine zutiefst objektorientierte Angelegenheit: Diese Methode wird aufgerufen, sobald Sie ein neues Objekt der Klasse classEuro erzeugen. Dabei können Sie beispielsweise dem Objekt erste Variablen oder Parameter mit auf den Weg geben und Verhalten sowie Eigenschaften des Objektes schon beim Start beeinflussen. Der Konstruktor bleibt aber in diesem Programm leer.

Formularkram

Basteln Sie ein kleines Formular mit einem Textfeld, zwei Radiobuttons und einem Button zum Starten der Umrechnung. Das reicht vorerst, um das Programm zu steuern. Das Formular sollte so aussehen:

Formularentwurf in C#

Die Namen von Textfeld, Radiobuttons und Button lassen Sie auf den Default-Werten, also „textBox1“, „radioButton1“ und „radioButton2“. Ansonsten können Sie sich gerne gestalterisch austoben.

Der Programmablauf wird so aussehen: Der Benutzer gibt eine Zahl ein, entscheidet wie er umrechnen möchte und startet dann die Umrechnung. Den gesamten Code hierfür bringen wir im Click-Event des Buttons unter.

Klicken Sie also doppelt auf den Button. Es öffnet sich das Code-Fenster zur Klasse „Form.cs“ mit der leeren Funktion

private void button1_Click(object sender, System.EventArgs e)

{

}

Füllen Sie diese Funktion mit folgendem Code:

private void button1_Click(object sender, System.EventArgs e)

{

classEuro oEuro = new classEuro();

try

{

oEuro.Wert = Convert.ToDouble(this.textBox1.Text);

if (radioButton1.Checked)

{

oEuro.toDM();

}

else if (radioButton2.Checked)

{

oEuro.toEuro();

}

oEuro.runde();

this.textBox1.Text = Convert.ToString(oEuro.Wert);

}

catch(FormatException ex)

{

MessageBox.Show(ex.ToString(), "Bitte nur Zahlen eingeben");

//MessageBox.Show("Bitte geben Sie nur Zahlen ein.", "Fehler");

}

}

Nehmen wir uns den Code vor. Mit der Zeile

classEuro oEuro = new classEuro();

erzeugen Sie ein Objekt namens „oEuro“ der Klasse „classEuro“. Das muss sein, um die Klasse überhaupt benutzen zu können.

Die nächste Zeile heißt try — darum kümmern wir uns gleich. Sehen Sie sich zunächst die Zeile

oEuro.Wert = Convert.ToDouble(this.textBox1.Text);

an. Hier weisen Sie der Eigenschaft „Wert“ des Objekts oEuro den Inhalt der Textbox zu. Damit das Ganze berechenbar wird, verwandeln Sie den Zeichenketteninhalt der Textbox in eine Fließkommazahl. In der Klasse greift die Initialisierng der Variablen „Wert“ mit „set“. Sprich: die frisch konvertierte Fließkommazahl wird in

set

{

myWert = value;

}

der privaten Variablen „myWert“ zugewiesen.

In der Konvertierung nach „Double“ steckt allerdings eine dicke Fehlerquelle: was ist, wenn der Benutzer keine Zahl, sondern ein Wort eingibt oder vor einer Eingabe auf den „Berechnen“-Button klickt? Dann fliegt Ihnen das Programm mit einer satten Fehlermeldung um die Ohren. Doch diese Fehlermeldung hat auch ihr Gutes. Sie verrät nämlich, dass es sich um eine „FormatException“ handelt. Und die fangen wir gleich ab.

Doch denken wir zunächst noch positiv: Es hat alles geklappt und die Umrechnung steht kurz bevor. Je nachdem welcher Radiobutton aktiv ist, entscheidet das Programm welche Methode aufgerufen wird — die Umrechnung von Euro nach DM mit „oEuro.toDM()“ oder umgekehrt mit „oEuro.toEuro()“. Ein Blick zurück in den Quelltext der Klasse zeigt: die entsprechende Methode belegt die Variable „myWert“ mit dem entsprechenden Ergebnis. Abgerufen wird es mit

this.textBox1.Text = Convert.ToString(oEuro.Wert);

Hier tritt die in der Variablendefinition von „Wert“ mit „get“ fest gelegte Aktion in Kraft:

get

{

return myWert;

}

Übrigens hätten Sie ohne weiteres die Euro-Umrechnung auch in dieses „get“ mit hinein packen können. Das würde allerdings der Klasse ein wenig Flexibilität nehmen, wenn Sie diese später erweitern.

Fehler behandeln

Kommen wir zu den Lieblingen aller Programmier: Fehler, Ausnahmen, Bugs. Einen solchen Fehler provozieren wir schon mit der Textbox: was tun, wenn der liebe Benutzer da tatsächlich Text eingibt? Wie schon angedeutet, erzeugt dies eine Fehlermeldung namens „FormatException“. Und den fängt „catch“ ab. Damit „catch“ weiß, was es wann fangen muss, brauchen wir zuvor noch einen Werfer — das ist „try“. Packen Sie in dieses „try“ den Code hinein, der einen Fehler erzeugen könnte. Wie in diesem Beispiel gezeigt, passt auch zusätzlicher Code mit hinein, der von dem Fehlergefährdeten Programmteil abhängt.

Was macht also catch? Sobald eine Fehlermeldung auftaucht, überprüft „catch(FormatException ex)“ ob es sich da um einen Fehler von eben jenem Typ handelt und speichert die Fehlermeldung in „ex“. Falls der Fehler auftritt, erscheint die gute alte Messagebox mit einer ausführlichen Fehler Meldung. Um die Meldung darzustellen, verwandeln Sie die zunächst in einen String. Wer es weniger ausführlich will, nimmt die auskommentierte Meldung eine Zeile darunter – für den Benutzer ist die sicher verständlicher.

Diesen try-catch-Mechanismus sollten Sie sich gut verinnerlichen — denn das ist der beste Weg, Fehler abzufangen.

Eine runde Sache

Damit hätten Sie den Euro-Umrechner fertig. Drücken Sie die Taste [F5], um einen Probelauf zu starten und rechnen Sie ein paar Beträge um.

Dabei fällt Ihnen sicher ein Schönheitsfehler auf: Das Ergebnis ist nicht gerundet. Also schließen Sie das Programm und machen Sie sich noch ein Mal an den Quellcode.

Zum Runden bietet sich eine eigene Methode an, die Sie in der Klasse „classEuro.cs“ unterbringen. Probieren Sie es mit folgendem Source-Code:

public void runde()

{

myWert = Convert.ToDouble(Convert.ToInt64(myWert * 100 + 0. 5)) / 100;

}

Das hatten wir schon im Informatik-Kurs an der Schule, als noch klar war, dass wir Computer ausschließlich zum Berechnen quadratischer Gleichungen benutzen dürfen: Wir runden auf die brutale Tour indem wir unserem Wert die Nachkommastellen abschneiden. Zack. Doch vorher müssen wir ihn noch ein wenig behandeln: Um auf zwei Stellen nach dem Komma zu runden, multiplizieren wir den Wert erst ein Mal mit 100 und dann geben wir noch 0,5 hinzu. Dann schneiden wir mit „Convert.ToInt64“ alle Nachkommastellen ab, verwandeln es in einen „Double“ zurück und teilen wieder alles durch 100.

Wozu der Aufwand, wenn es „math.round()“ gibt, werden Sie fragen. Ganz einfach diese Funktion rundet nicht kaufmännisch, sondern rundet bei einer ,5 als Nachkommastelle noch ab. Sprich aus „Math.Round(10.565, 2);“ wird 10,56. Und der Kaufmann möchte an dieser Stelle eine 10,57. Außerdem ist es ein guter Weg, heftig Variablentypen zu konvertieren.

Diese neue Methode können Sie einfach aufrufen: Packen Sie in „Form1.cs“ den Aufruf

oEuro.runde();

vor die Ausgabezeile

this.textBox1.Text = Convert.ToString(oEuro.Wert);

Schon erscheint ein rundes Ergebnis nach der Euro-Umrechnung.

Das Programm ist damit so weit fertig. Jetzt sehen wir, wie sich die Euro-Klasse auch anderweitig verwenden lässt.

Eine Konsolenanwendung schreiben

Speichern Sie den Euro-Umrechner-Code mit [Strg – S] und klicken Sie dann „File – Close Solution“. Damit verschwindet unser schöner Rechner. Aber er wird gleich wieder in anderem Gewand auftauchen.

Klicken Sie auf „File – New – Project“ und wählen Sie „Console Application“. Nennen Sie das Ganze „conseur“ und klicken Sie auf „Ok“.

Es öffnet sich die Vorlage für eine Konsolen-Applikation:

using System;

namespace conseur

{

///

/// Summary description for Class1.

///

class Class1

{

static void Main(string[] args)

{

//

// TODO: Add code to start application here

//

}

}

}

Bauen Sie dieses Gerüst aus zu folgendem Programm:

using System;

namespace conseur

{

///

/// Summary description for Class1.

///

class Class1

{

static void Main(string[] args)

{

int choice;

classEuro oEuro = new classEuro();

Console.WriteLine("Willkommen zum Euro-Umrechner.");

Console.WriteLine("1. Geben Sie bitte den Betrag ein:");

try

{

oEuro.Wert = Convert.ToDouble(Console.ReadLine());

Console.WriteLine("2. (1) für DM -> Euro (2) für Euro -> DM");

choice = Convert.ToInt16(Console.ReadLine());

if (choice == 1)

{

oEuro.toEuro();

}

else if (choice == 2)

{

oEuro.toDM();

}

oEuro.runde();

Console.WriteLine("Das macht dann {0}", oEuro.Wert);

Console.WriteLine("-- Bitte [Return] drücken --");

Console.ReadLine();

}

catch(FormatException ex)

{

Console.WriteLine("Fehler: Bitte nur Zahlen eingeben.

{0}", ex);

Console.ReadLine();

}

}

}

}

Das ist ein simples Kommandozeilen-Interface für den Euro-Umrechner: Mit „console.Writeline()“ geben Sie einen Text aus, mit „console.Readline()“ liest das Programm eine Eingabe und weist sie auf Wunsch einer Variablen zu. Beim Einlesen der Daten haben wir dieselben Fehlerquellen wie beim Einlesen aus dem Textfeld der Windows-Anwendung. Und die Fehler fangen wir genauso ab. Der einzige wesentliche Unterschied ist die Variable „choice“, die jeweils die Benutzereingabe übernimmt.

Sehr robust ist dieser Code noch nicht — gibt ein Benutzer die „3“ ein erhält er als Ergebnis den anfangs eingegebenen Betrag. Aber wir benötigen dieses Gerippe ja auch nur zu Demonstrationszwecken. Denn jetzt klicken Sie auf „File – Add Existing Item“ und suchen im folgenden Fenster die Klasse „classEuro“ aus dem Projekt „Csharp1“. Nach dem Klick auf „Ok“ erscheint die Klasse rechts oben im „Solution Explorer“. Klicken sie doppelt auf den Eintrag „classEuro“ und ändern sie im Quelltext die Zeile

namespace Csharp1

um in

namespace conseur

Damit ist Ihr Konsolenprogramm fertig. Sie müssen nur noch auf [F5] drücken und können endlich wieder Konsolenluft schnuppern wie einst, als Basic noch dazu diente, quadratische Gleichungen zu lösen.

Was ist geschehen? Sie haben einfach die Klasse „classEuro“ in das neue Konsolenprojekt übernommen und können dessen Eigenschaften und Methoden genauso nutzen. Ein anderer Programmierer muss eigentlich nicht ein Mal wissen, was im Inneren des Objektes eigentlich vorgeht. Er muss nur die Schnittstellen und Methoden kennen.

Genau das ist objektorientierte Programmierung mit C#.

Das erwartet Umsteiger

  • Der Strichpunkt: Hinter jede Anweisung gehört das Semikolon.
  • Die Objekte: In C# ist alles objektorientiert — das erfordert einen neuen Programmierstil. (Wir hatten schließlich lange genug Zeit, uns daran zu gewöhnen 😉 )
  • Die Schreibweise der Variablen: C# unterscheidet zwischen Groß- und Kleinschreibung
  • Die Variablendeklaration: Aus ist’s mit „egal welcher Typ“. Ab sofort müssen Variablen deklariert werden.
  • Teils andere Operatoren: Wer wie in Basic gewohnt aus zwei 2 ^ 2 eine 4 errechnen will, kann dies vergessen. Das heißt jetzt „math.pow();“
  • Code-Blöcke in Funktionen, Schleifen und Bedingungen sind in geschweiften Klammern zusammengefasst.
  • Die if-Anweisung kommt ohne then daher. Dafür steht der zu if gehörende Code in geschweiften Klammern. Sie werden „then“ nicht vermissen.

Ähnliche Beiträge

    None Found