Compiler sagt nein.
Dein Einstieg in die Programmierwelt: was ein Programm überhaupt ist, warum Compiler und Interpreter sich nicht mögen, welcher Datentyp in welche Schublade gehört und wie man eine Variable deklariert, ohne dass jemand nein sagt. Am Ende liest du Schleifen, Arrays und erste Methoden. Der Compiler bleibt unerbittlich, aber wenigstens ehrlich.
Von „Was ist ein Programm?“ bis zur ersten Methode.
Zehn Stufen, jede trainiert genau eine Fähigkeit. Erst erklärt, dann vorgemacht, dann bist du dran. Die ersten drei Aufgaben jeder Stufe kommen mit Hinweis. Eine Stufe gilt als gemeistert, wenn du 8 der letzten 10 Aufgaben ohne Hilfe richtig hast. Erst dann geht die nächste Tür auf. Wer schummelt, betrügt nur sein zukünftiges Prüfungs-Ich.
Stufe wird geladen …
Lektion
Bereit? Dann weg mit dem Spickzettel.
Sobald du startest, wird die Lektion ausgeblendet. Du kannst jederzeit zurück, die offene Aufgabe verfällt dann aber.
Alles zum Nachschlagen. Zeile für Zeile.
Zehn Kapitel vom ersten Algorithmus bis zur ersten Methode, mit Beispielen, Abläufen in Zeitlupe und einem Kurz-Check. Der Code in diesem Modul läuft nicht im Browser, sondern wurde vorab mit dem echten C#-Compiler geprüft. Im Sprint und in der Prüfung ist das Nachschlagwerk gesperrt. Neu hier? Dann fang im Lernpfad an.
Was ist ein Programm?
Du weißt, was ein Programm ist und wie aus einer Idee Schritt für Schritt Anweisungen werden.
Ein Computer ist unfassbar schnell und unfassbar dumm. Er macht exakt, was dasteht. Nicht das, was du gemeint hast. Programmieren heißt deshalb: eine Aufgabe so genau in Schritte zerlegen, dass selbst eine Maschine ohne Fantasie sie richtig erledigt.
Diese Schritte schreibst du als Quelltext in einer Programmiersprache auf, zum Beispiel C#. Der Quelltext ist für Menschen lesbar. Daraus entsteht später ein Programm, das der Computer ausführt.
Eine genaue Schrittfolge zur Lösung einer Aufgabe heißt Algorithmus. Das Wort klingt nach Mathe-Olymp. Gemeint ist aber nur ein sehr gründliches Rezept.
Console.WriteLine("Wie viele Ports hat der Switch?"); int ports = int.Parse(Console.ReadLine()!); int frei = ports - 2; Console.WriteLine("Freie Ports: " + frei);
- Eingabe: Das Programm fragt und liest die Antwort von der Tastatur.
- Verarbeitung: Es rechnet 24 − 2, weil zwei Ports für den Uplink reserviert sind.
- Ausgabe: Das Ergebnis erscheint im Konsolenfenster.
- Jeder Schritt steht in einer eigenen Zeile. Der Computer arbeitet sie von oben nach unten ab, ohne zu fragen, ob das sinnvoll ist.
Hochsprache und Maschinensprache
Die CPU kennt nur sehr einfache Befehle als Bitmuster, etwa „lade Wert“, „addiere“, „springe“. Das ist Maschinensprache. Kein Mensch will darin eine Gerätedatenbank schreiben. Darum gibt es Hochsprachen wie C#, Python oder Java. Sie sind lesbarer und müssen vor oder während der Ausführung übersetzt werden. Wie genau, klärt Kapitel 2.
Ein Algorithmus aus dem Alltag
„Drucker einrichten“ als Schrittfolge: Treiber herunterladen, Treiber installieren, Drucker anschließen, Testseite drucken. Vertauschst du zwei Schritte, wird es spannend. Genauso ist es im Code: Die Reihenfolge ist Teil der Lösung.
Syntax und Semantik
Die Syntax ist die Rechtschreibung einer Sprache: Wo steht das Semikolon, welche Klammer gehört wohin. Die Semantik ist die Bedeutung: Was passiert, wenn die Zeile läuft. Ein Programm kann syntaktisch perfekt sein und trotzdem Unsinn tun. Der Computer merkt das nicht. Du hoffentlich schon.
Wo dir Programme als Systemintegrator begegnen
Skripte, die Benutzer anlegen. Tools, die Logdateien durchsuchen. Monitoring, das bei vollem Speicher Alarm schlägt. Du musst kein Softwareentwickler werden. Aber wer Code lesen kann, muss nicht jedes Mal hoffen, dass das Skript aus dem Forum schon passen wird.
Auf deinem Rechner ausprobieren
Schreibe in normalen deutschen Sätzen einen Algorithmus für „Passwort zurücksetzen“ mit mindestens fünf Schritten. Markiere, was Eingabe, Verarbeitung und Ausgabe ist.
Musterlösung ansehen
- Benutzer gibt seinen Anmeldenamen ein. (Eingabe)
- System prüft, ob es den Namen gibt. (Verarbeitung)
- System erzeugt einen einmaligen Code. (Verarbeitung)
- System schickt den Code per E-Mail. (Ausgabe)
- Benutzer gibt Code und neues Passwort ein. (Eingabe)
- System prüft Code und Passwortregeln und meldet Erfolg oder Fehler. (Verarbeitung, Ausgabe)
Compiler, Interpreter und .NET
Du kannst Compiler und Interpreter unterscheiden und kennst den Weg deines C#-Programms bis zur CPU.
Die CPU versteht nur Maschinensprache. Dein Quelltext muss also übersetzt werden. Dafür gibt es zwei Grundideen.
Ein Compiler übersetzt das ganze Programm, bevor es startet. Findet er einen Fehler, startet gar nichts. Er ist der Kollege, der den kompletten Bericht liest, bevor er unterschreibt.
Ein Interpreter liest das Programm während der Ausführung Anweisung für Anweisung und führt sie sofort aus. Ein Fehler in Zeile 50 fällt erst auf, wenn Zeile 50 dran ist. Bis dahin lief alles prima. Vielleicht sogar beim Kunden.
| Compiler | Interpreter | |
|---|---|---|
| Wann wird übersetzt? | vorher, alles auf einmal | während der Ausführung, Schritt für Schritt |
| Syntaxfehler | vor dem Start, nichts läuft | erst, wenn die Zeile dran ist |
| Ergebnis | ausführbare Datei | keine eigene Datei, Quelltext + Interpreter nötig |
| Tempo beim Ausführen | meist schneller | meist langsamer |
| Typische Sprachen | C, C++, Go, Rust | Python, PowerShell, Bash, JavaScript (klassisch) |
Console.WriteLine("Backup startet"); Console.WriteLine("Kopiere Dateien"); Console.WriteLine("Fertig")
- Der C#-Compiler liest das ganze Programm, bevor irgendetwas läuft.
- In Zeile 3 fehlt das Semikolon. Er meldet
CS1002: ; erwartet. - Es entsteht kein Programm. Die Konsole zeigt gar nichts, auch nicht die ersten beiden Zeilen.
- Ein Interpreter hätte „Backup startet“ und „Kopiere Dateien“ noch ausgegeben und wäre erst in Zeile 3 gestolpert.
Der Weg eines C#-Programms
IL (Intermediate Language) ist ein Zwischencode, der auf jeder Plattform mit .NET läuft. Die CLR (Common Language Runtime) ist die Laufzeitumgebung: Sie lädt das Programm, verwaltet den Speicher und räumt hinter dir auf. Der JIT-Compiler (Just in Time) übersetzt den IL-Code erst beim Ausführen in Maschinencode für genau diese CPU.
C#, .NET und das SDK
C# ist die Sprache. .NET ist die Plattform darunter: Laufzeit plus riesige Bibliothek fertiger Bausteine wie Console. Das SDK (Software Development Kit) brauchst du zum Entwickeln, es enthält den Compiler. Zum reinen Ausführen reicht die Runtime.
Und welche Variante ist besser?
Keine. Kompilierte Programme sind meist schneller und melden Tippfehler früh. Interpretierte Skripte änderst du einfach und startest sie sofort neu, ideal für schnelle Admin-Aufgaben. Darum schreibst du PowerShell-Skripte und keine C#-Programme, um mal eben 30 Benutzer anzulegen.
Fehlerarten im Vorgriff
Ein Syntaxfehler verletzt die Regeln der Sprache. Den findet der Compiler. Ein Laufzeitfehler tritt erst beim Ausführen auf, etwa wenn jemand „abc“ eintippt, wo eine Zahl erwartet wird. Ein logischer Fehler rechnet einfach falsch, ohne dass irgendwer meckert. Der Compiler sagt bei vielem nein. Bei Logik sagt er leider gar nichts.
Auf deinem Rechner ausprobieren
Lege mit dotnet new console -o Test ein Projekt an. Lösche in Program.cs ein Semikolon und starte mit dotnet run. Lies die Fehlermeldung: Welche Datei, welche Zeile, welcher Code?
Musterlösung ansehen
Die Meldung sieht etwa so aus: Program.cs(1,34): error CS1002: ; erwartet. Datei Program.cs, Zeile 1, Spalte 34, Fehlercode CS1002. Ausgegeben wird nichts, denn der Compiler hat nein gesagt.
Aufbau eines C#-Programms
Du liest ein kleines Programm und weißt, wofür jedes Zeichen darin steht.
Jetzt wird es konkret. Ein C#-Programm besteht aus Anweisungen. Jede Anweisung ist ein Befehl, zum Beispiel „schreibe diese Zeile“. Am Ende jeder Anweisung steht ein Semikolon. Es ist der Punkt am Satzende. Fehlt er, hat der Compiler Redebedarf.
Mehrere Anweisungen kannst du in geschweiften Klammern { } zu einem Block zusammenfassen. Alles hinter // ist ein Kommentar: Der Compiler ignoriert ihn, dein Kollege in sechs Monaten zum Glück nicht.
;. Text steht in doppelten Anführungszeichen. Groß- und Kleinschreibung zählt: console ist nicht Console.Console.WriteLine("Hallo Welt!");
Consoleist das Konsolenfenster, genauer: eine fertige Klasse aus .NET.- Der Punkt heißt „gehe in“. Du greifst damit auf etwas zu, das zu
Consolegehört. WriteLineist eine Methode, also ein Befehl mit Namen. Sie schreibt eine Zeile und springt danach in die nächste.- Die runden Klammern übergeben, womit die Methode arbeiten soll. Hier ist es der Text
"Hallo Welt!". - Das Semikolon beendet die Anweisung.
Lesen, schreiben, kommentieren
Console.ReadLine() wartet, bis jemand etwas tippt und Enter drückt, und liefert den Text zurück. Console.Write() schreibt ohne Zeilenumbruch.
// Fragt nach dem Namen und begrüßt Console.Write("Name: "); string? name = Console.ReadLine(); Console.WriteLine("Hallo " + name);
Zwei Formen desselben Programms
Neue .NET-Projekte erlauben „Top-Level-Anweisungen“: Du schreibst die Befehle direkt in die Datei. In älteren Büchern und in vielen Prüfungsaufgaben steht drumherum noch eine Klasse mit der Methode Main. Dort beginnt das Programm. Das ist dasselbe Programm mit mehr Verpackung.
class Program { static void Main() { Console.WriteLine("Hallo Welt!"); } }
Auf deinem Rechner ausprobieren
Dieses Modul führt keinen Code im Browser aus. Dafür brauchst du nur das kostenlose .NET SDK und einen Editor wie VS Code. Im Terminal:
dotnet new console -o MeinTool cd MeinTool dotnet run
Dein Code gehört in die Datei Program.cs.
WriteLine falsch geschrieben, Anführungszeichen vergessen, Semikolon vergessen. Drei Fehler, die jeder macht. Nur dass der Compiler sie jedes Mal wieder persönlich nimmt.Auf deinem Rechner ausprobieren
Schreibe ein Programm, das nach einem Raum fragt und „Ticket für Raum … erfasst.“ ausgibt.
Musterlösung ansehen
Console.WriteLine("Raum?"); string? raum = Console.ReadLine(); Console.WriteLine("Ticket für Raum " + raum + " erfasst.");
Datentypen
Du wählst für jeden Wert den passenden Datentyp und kennst seine Grenzen.
Im Speicher liegt alles als Nullen und Einsen. Das Bitmuster 01000001 kann die Zahl 65 sein oder der Buchstabe A. Woher weiß das Programm, was gemeint ist? Durch den Datentyp.
Der Datentyp legt drei Dinge fest: welche Werte erlaubt sind, wie viel Speicher dafür reserviert wird und was man damit tun kann. Mit Zahlen rechnest du, Texte hängst du aneinander. Andersherum wird es lustig, aber selten richtig.
C# ist streng typisiert: Jeder Wert hat einen festen Typ, und der Compiler prüft das. Text in eine Zahl stopfen? Compiler sagt nein.
| Typ | Inhalt | Größe | Beispiel |
|---|---|---|---|
int | ganze Zahl, ca. ±2,1 Milliarden | 32 Bit | 24 |
long | große ganze Zahl | 64 Bit | 8000000000L |
double | Kommazahl, nicht immer exakt | 64 Bit | 3.5 |
decimal | exakte Dezimalzahl, etwa für Geld | 128 Bit | 19.99m |
bool | wahr oder falsch | 1 Byte | true |
char | genau ein Zeichen | 16 Bit | 'A' |
string | Text, beliebig lang | je nach Länge | "Router" |
int. Geld → decimal mit m. Messwert mit Komma → double. Ja/Nein → bool. Ein Zeichen in '…' → char. Text in "…" → string. Im Code steht das Komma als Punkt: 3.5.int zahl = 40; string text = "40"; double komma = 40.0; Console.WriteLine(zahl + 2); Console.WriteLine(text + 2); Console.WriteLine(komma / 3);
zahlist einint. Plus 2 wird gerechnet: 42.textist einstring. Plus 2 wird angehängt: „402“. Der Typ entscheidet, was+bedeutet.kommaist eindouble. Die Division liefert Nachkommastellen.- Ein deutsches Windows zeigt dabei ein Komma statt eines Punktes. Im Quelltext steht immer der Punkt.
Wertebereich und Überlauf
Ein int hat 32 Bit. Damit passen Zahlen von −2.147.483.648 bis 2.147.483.647 hinein. Was passiert eine Zahl darüber? Standardmäßig springt C# ohne Warnung ans andere Ende. Das nennt man Überlauf.
int maximum = int.MaxValue; maximum = maximum + 1; Console.WriteLine(maximum);
Für größere Werte gibt es long mit 64 Bit. Dateigrößen in Byte oder Weltbevölkerung? long.
Warum Geld decimal braucht
double speichert Zahlen binär. Viele Dezimalbrüche wie 0,1 lassen sich so nicht exakt darstellen. Für Messwerte ist der winzige Fehler egal. Für Rechnungen nicht.
double d = 0.1 + 0.2; decimal m = 0.1m + 0.2m; Console.WriteLine(d == 0.3); Console.WriteLine(m == 0.3m);
char und string
'A' in einfachen Anführungszeichen ist ein Zeichen. "A" in doppelten ist ein Text, der zufällig ein Zeichen lang ist. Für den Compiler zwei verschiedene Typen.
char zeichen = "A";
Wertetypen und Verweistypen
int, double, bool und char sind Wertetypen: Die Variable enthält den Wert selbst. string ist ein Verweistyp: Die Variable zeigt auf einen Text im Speicher. Für den Einstieg reicht: Beides funktioniert, wie du es erwartest. Der Unterschied wird später bei Objekten wichtig.
decimal-Werte brauchen das m: 19.99m. Ohne Suffix ist 19.99 ein double, und der Compiler verweigert die Zuweisung. Und int.MaxValue + 1 gibt keine Fehlermeldung, sondern eine sehr negative Überraschung.Auf deinem Rechner ausprobieren
Lege für einen Laptop sinnvolle Variablen an: Hersteller, Arbeitsspeicher in GB, Preis, Akkustand in Prozent mit Komma, verschlüsselt ja/nein. Gib alles aus.
Musterlösung ansehen
string hersteller = "Contoso"; int ramGb = 16; decimal preis = 899.00m; double akku = 87.5; bool verschluesselt = true; Console.WriteLine(hersteller + " " + ramGb + " " + preis + " " + akku + " " + verschluesselt);
Variablen deklarieren und initialisieren
Du unterscheidest Deklaration, Initialisierung und Zuweisung sicher und schreibst sie selbst.
Eine Variable ist eine beschriftete Schublade im Speicher. Der Datentyp sagt, was hineinpasst, der Name steht auf dem Etikett. Mit Variablen passieren drei verschiedene Dinge, und die Prüfung fragt gern genau danach:
- Deklarieren: Die Schublade wird angelegt.
int ports;Typ und Name, sonst nichts. - Initialisieren: Die Schublade bekommt ihren ersten Wert.
ports = 24; - Zuweisen: Später kommt ein neuer Wert hinein, der alte fliegt raus.
ports = 48;
Meist erledigst du die ersten beiden in einer Zeile: int ports = 24; Deklaration mit Initialisierung.
int ports; ports = 24; Console.WriteLine(ports); ports = 48; Console.WriteLine(ports);
int ports;deklariert die Variable. Sie hat noch keinen Wert, den man lesen dürfte.ports = 24;initialisiert sie mit dem ersten Wert.- Die Ausgabe zeigt 24.
ports = 48;ist eine Zuweisung. Kein Typ davor, denn die Schublade gibt es schon.- Die zweite Ausgabe zeigt 48. Die 24 ist weg, ohne Abschiedsbrief.
Lesen vor dem ersten Wert
C# lässt dich eine lokale Variable nicht lesen, bevor sie einen Wert hat. Der Compiler meldet CS0165: Verwendung der nicht zugewiesenen lokalen Variable. Er hat recht: In der Schublade liegt noch nichts Sinnvolles.
int fehler; Console.WriteLine(fehler);
Doppelt deklariert
Zweimal dieselbe Schublade anlegen geht nicht. Wer nur einen neuen Wert will, lässt den Typ weg.
int vlan = 10; int vlan = 20;
Gute Namen
Ein Name beginnt mit einem Buchstaben oder Unterstrich, danach dürfen Buchstaben, Ziffern und Unterstriche folgen. Keine Leerzeichen, keine Bindestriche, keine reservierten Wörter wie class oder int. Üblich ist camelCase: freiePorts, anzahlGeraete. Und bitte nicht x2, außer du willst dein zukünftiges Ich ärgern.
var und const
Bei var leitet der Compiler den Typ aus dem Startwert ab. Deshalb braucht var immer eine Initialisierung. Der Typ bleibt danach fest. const macht einen Wert unveränderlich, er muss sofort feststehen.
var hersteller = "Contoso"; const int MaxPorts = 48; Console.WriteLine(hersteller + " " + MaxPorts);
Werte tauschen
Zwei Variablen tauschen ihre Inhalte? Dafür brauchst du eine dritte Schublade als Zwischenablage. Sonst ist ein Wert verloren.
int a = 1; int b = 2; int tmp = a; a = b; b = tmp; Console.WriteLine(a + " " + b);
int ports = 24; und später nochmal int ports = 48;? Doppelte Deklaration, Compiler sagt nein. Und var x; ohne Wert geht auch nicht: Woher soll der Compiler den Typ kennen? Raten ist nicht sein Ding.Auf deinem Rechner ausprobieren
Deklariere eine Variable für die Anzahl offener Tickets ohne Startwert. Initialisiere sie danach mit 5, erhöhe sie dann um 3 und gib sie aus.
Musterlösung ansehen
int offeneTickets; offeneTickets = 5; offeneTickets = offeneTickets + 3; Console.WriteLine(offeneTickets);
Typumwandlung, Ein- und Ausgabe
Du bringst Eingaben in den richtigen Typ und gibst Werte sauber aus.
Die Tastatur liefert immer Text. Tippt jemand 42, bekommst du den string „42“, nicht die Zahl 42. Rechnen willst du aber mit Zahlen. Also musst du umwandeln.
Manche Umwandlungen macht C# von selbst, weil dabei nichts verloren geht: implizit. Eine kleine Zahl passt immer in eine große Schublade. Bei anderen könnte etwas verloren gehen. Die musst du explizit verlangen, damit klar ist: Du weißt, was du tust. Zumindest offiziell.
Console.ReadLine() liefert string. Mit int.Parse wird Text zur Zahl. (int) vor einem double schneidet ab, statt zu runden. $"…{wert}…" setzt Werte in Text ein.Console.WriteLine("Wie viele Geräte?"); string eingabe = Console.ReadLine()!; int anzahl = int.Parse(eingabe); double proRaum = anzahl / 4.0; Console.WriteLine($"{anzahl} Geräte, {(int)proRaum} volle pro Raum");
ReadLineliefert den Text „10“.int.Parsemacht daraus die Zahl 10.10 / 4.0ist wegen4.0eine double-Division: 2,5.(int)proRaumschneidet ab: 2. Gerundet wird nicht.- Das
$vor dem Text erlaubt Platzhalter in{ }. Das heißt String-Interpolation.
Implizit und explizit
Von int nach long oder double geht nichts verloren, das passiert automatisch. Umgekehrt muss ein Cast her: der Zieltyp in runden Klammern.
int klein = 7; long gross = klein; double kommazahl = klein; double messung = 9.99; int abgeschnitten = (int)messung; Console.WriteLine(gross + " " + kommazahl + " " + abgeschnitten);
double messung = 9.99; int wert = messung;
Parse und TryParse
int.Parse("abc") kompiliert problemlos und stürzt beim Ausführen mit einer FormatException ab. Ein klassischer Laufzeitfehler. int.TryParse versucht es höflicher: Es liefert true oder false und legt die Zahl bei Erfolg in die out-Variable.
string eingabe = "abc"; if (int.TryParse(eingabe, out int zahl)) { Console.WriteLine(zahl * 2); } else { Console.WriteLine("Das ist keine Zahl."); }
Text zusammensetzen
Drei Wege führen zum selben Ergebnis. Interpolation ist meist am lesbarsten.
string name = "NAS-3"; int frei = 512; Console.WriteLine(name + ": " + frei + " GB frei"); Console.WriteLine($"{name}: {frei} GB frei"); Console.WriteLine(name + ": " + frei.ToString() + " GB frei");
Achtung bei +: C# arbeitet von links nach rechts. "Summe: " + 2 + 3 ergibt „Summe: 23“, weil links schon Text steht. "Summe: " + (2 + 3) ergibt „Summe: 5“.
(int)9.99 ist 9, nicht 10. Abschneiden ist kein Runden. Und int.Parse auf eine Benutzereingabe ohne Prüfung ist eine Wette darauf, dass niemand „zwölf“ tippt. Diese Wette verlierst du.Auf deinem Rechner ausprobieren
Lies einen Preis mit Komma ein (z. B. 19,99), wandle ihn in decimal um und gib den Preis inklusive 19 % Mehrwertsteuer aus. Fang eine ungültige Eingabe mit TryParse ab.
Musterlösung ansehen
string eingabe = Console.ReadLine()!; if (decimal.TryParse(eingabe, out decimal netto)) { decimal brutto = netto * 1.19m; Console.WriteLine($"Brutto: {brutto:0.00}"); } else { Console.WriteLine("Ungültiger Preis."); }
Operatoren und Berechnungen
Du rechnest Ausdrücke so aus, wie C# sie ausrechnet.
Ein Backup hat 10 GB, drei Festplatten sollen es sich teilen. 10 / 3 ergibt in C# 3. Kein Bug: Zwei int-Werte ergeben eine Integerdivision, und der Nachkommateil wird abgeschnitten. Niemand hat dich gefragt, ob du den Rest noch brauchst.
int, ist das Ergebnis int. Ist einer double, gibt es Nachkommastellen. Punkt vor Strich gilt auch hier, Klammern gehen vor.int geraete = 10; Console.WriteLine(geraete / 3); Console.WriteLine(geraete % 3); Console.WriteLine(geraete / 3.0 > 3);
10 / 3: beideint, also 3 mit abgeschnittenem Rest.10 % 3: 3 × 3 = 9, es bleibt 1. Modulo liefert genau diesen Rest.3.0ist eindouble, also wird echt geteilt: etwa 3,33.- 3,33 ist größer als 3. Der Vergleich ergibt
True.
Abkürzungen beim Zuweisen
x += 5 bedeutet x = x + 5. x++ erhöht um 1. Steht das ++ hinter der Variablen, liefert der Ausdruck noch den alten Wert. Steht es davor, den neuen.
int x = 5; Console.WriteLine(x++); Console.WriteLine(x); Console.WriteLine(++x);
Logik
&& ist nur wahr, wenn beide Seiten wahr sind. || reicht eine wahre Seite. ! dreht um. && wird vor || ausgewertet.
bool online = true; bool wartung = false; Console.WriteLine(online && !wartung);
Rangfolge
Reihenfolge von oben nach unten: Klammern, dann * / %, dann + -, dann Vergleiche, dann &&, dann ||, zuletzt die Zuweisung.
double d = 10 / 4; ergibt 2, nicht 2,5. Rechts wird zuerst mit int gerechnet, erst danach landet die 2 im double. Die Variable kann nichts dafür.Auf deinem Rechner ausprobieren
Lies eine Zahl ein und gib aus, ob sie gerade ist. Tipp: Modulo.
Musterlösung ansehen
int zahl = int.Parse(Console.ReadLine()!); Console.WriteLine(zahl % 2 == 0);
Verzweigungen
Du sagst vorher, welcher Zweig eines Programms läuft.
Freier Plattenplatz unter 10 %? Dann Warnung. Sonst alles gut. Genau das macht if: Es prüft einen Ausdruck, der true oder false ergibt, und entscheidet, welcher Block läuft.
bool ergeben. Vergleichen heißt ==, nicht =. Bei else if läuft nur der erste passende Zweig.int alter = 17; if (alter >= 18) { Console.WriteLine("Zutritt erlaubt."); } else { Console.WriteLine("Nö. Erst erwachsen werden."); }
alterenthält 17.- Das Programm prüft
17 >= 18. Das istfalse. - Der erste Block wird übersprungen, der
else-Block läuft. - Danach geht es unter der letzten Klammer weiter. Hier ist das Programm zu Ende.
else if
Die Zweige werden von oben geprüft. Der erste Treffer gewinnt, der Rest wird nicht mehr angesehen. Die Reihenfolge entscheidet also mit.
int frei = 8; if (frei < 5) { Console.WriteLine("Kritisch"); } else if (frei < 10) { Console.WriteLine("Warnung"); } else { Console.WriteLine("OK"); }
switch
Passt, wenn ein einziger Wert mit festen Möglichkeiten verglichen wird, etwa ein Menü. break beendet den Fall, default fängt alles andere auf.
string wahl = "2"; switch (wahl) { case "1": Console.WriteLine("Neues Gerät"); break; case "2": Console.WriteLine("Liste anzeigen"); break; default: Console.WriteLine("Unbekannt"); break; }
Der Klassiker
= weist zu, == vergleicht. C# fängt die Verwechslung hier ab, weil das Ergebnis kein bool ist:
int x = 5; if (x = 5) { Console.WriteLine("fünf"); }
== exakt: "Ja" == "ja" ist false. Und wer wert < 10 vor wert < 5 prüft, sieht den Zweig „Kritisch“ nie.Auf deinem Rechner ausprobieren
Lies einen Akkustand ein: unter 20 „Laden“, unter 80 „OK“, sonst „Voll“.
Musterlösung ansehen
int akku = int.Parse(Console.ReadLine()!); if (akku < 20) { Console.WriteLine("Laden"); } else if (akku < 80) { Console.WriteLine("OK"); } else { Console.WriteLine("Voll"); }
Schleifen
Du sagst genau, wie oft eine Schleife läuft und warum.
Zehn Geräte anpingen, zehnmal dieselbe Zeile schreiben? Spätestens bei 500 Geräten kündigst du. Eine Schleife wiederholt einen Block, solange eine Bedingung gilt.
i < 10 mit Start 0 sind es zehn, bei i <= 10 elf.for (int i = 1; i <= 3; i++) { Console.WriteLine("Port " + i); }
int i = 1läuft genau einmal.1 <= 3ist wahr, also läuft der Block: „Port 1“.i++macht aus 1 eine 2. Dann wieder prüfen.- Das passiert noch für 2 und 3. Danach ist
i4, und4 <= 3ist falsch. Schluss.
while und do while
while prüft vor dem Block und läuft vielleicht nie. do while prüft danach und läuft mindestens einmal.
int n = 5; while (n < 3) { Console.WriteLine("while"); n++; } do { Console.WriteLine("do"); n++; } while (n < 3);
foreach
Geht jedes Element einer Sammlung durch. Ohne Zähler, ohne Indexfehler, ohne Drama.
string[] geraete = { "Router", "Switch" }; foreach (string g in geraete) { Console.WriteLine(g); }
break und continue
break verlässt die Schleife ganz. continue springt direkt zum nächsten Durchlauf.
for (int i = 1; i <= 5; i++) { if (i == 2) continue; if (i == 4) break; Console.WriteLine(i); }
Endlosschleifen
Ändert sich die Bedingung nie, läuft die Schleife bis zum Abbruch. Im Terminal stoppt Strg+C das Programm. Der Lüfter dankt.
<= statt < liefert einen Durchlauf zu viel. Und bei while das Hochzählen zu vergessen, ist die häufigste Art, eine CPU zu heizen.Auf deinem Rechner ausprobieren
Gib die Zahlen von 1 bis 10 aus. Danach versuche es mit while statt for.
Musterlösung ansehen
for (int i = 1; i <= 10; i++) { Console.WriteLine(i); }
Arrays und erste Methoden
Du greifst auf Elemente eines Arrays zu und rufst kleine Methoden auf.
Für 200 Geräte willst du keine 200 Variablen. Ein Array hält mehrere Werte gleichen Typs mit fester Größe. Eine Liste kann wachsen und schrumpfen. Beide nummerieren ihre Elemente mit einem Index, und der beginnt bei 0. Nicht bei 1. Nie. Auch nicht montags.
Und wenn du dieselbe Berechnung an fünf Stellen brauchst, schreibst du sie einmal als Methode: ein benannter Codeblock, den du beliebig oft aufrufst. Einmal reparieren, überall behoben. Damit hast du alle Bausteine für ein erstes kleines Tool.
Length, Listen Count. Eine Methode mit Rückgabetyp braucht return. void heißt: gibt nichts zurück.static bool IstVoll(int belegt, int ports) { return belegt >= ports; } string[] namen = { "SW-1", "SW-2", "SW-3" }; int[] belegt = { 24, 18, 24 }; for (int i = 0; i < namen.Length; i++) { if (IstVoll(belegt[i], 24)) { Console.WriteLine(namen[i] + " ist voll"); } }
- Zwei Arrays: Index 0 gehört zu SW-1, Index 1 zu SW-2, Index 2 zu SW-3.
- Die Schleife läuft von 0 bis
Length − 1, also bis 2. - Bei jedem Durchlauf wird
IstVollaufgerufen. Die Werte landen in den Parameternbelegtundports. returnlieferttrueoderfalsean die Aufrufstelle zurück.- Nur bei
trueerscheint eine Meldung: SW-1 und SW-3.
Arrays anlegen
Mit festen Werten oder mit einer Größe. Neue int-Elemente enthalten 0, neue string-Elemente null.
int[] werte = new int[3]; werte[0] = 5; werte[2] = 7; Console.WriteLine(werte[0] + werte[1] + werte[2]); Console.WriteLine(werte.Length);
Ein Zugriff auf werte[3] kompiliert, stürzt aber beim Ausführen mit einer IndexOutOfRangeException ab.
Listen
List<string> ist eine Liste von Texten. Add hängt an, Remove entfernt das erste passende Element.
List<string> geraete = new List<string>(); geraete.Add("Router"); geraete.Add("Switch"); geraete.Remove("Router"); Console.WriteLine(geraete.Count); Console.WriteLine(geraete[0]);
Methoden: Ausgeben ist nicht Zurückgeben
Eine void-Methode tut etwas, etwa eine Meldung ausgeben. Eine Methode mit Rückgabetyp liefert einen Wert, mit dem du weiterarbeitest.
static void Melde(string text) { Console.WriteLine("Hinweis: " + text); } static int Summe(int a, int b) { return a + b; } Melde("Backup fertig"); Console.WriteLine(Summe(2, 3) * 10);
Die Werte beim Aufruf heißen Argumente, die Platzhalter in der Methode Parameter. Die Zuordnung erfolgt über die Reihenfolge, nicht über den Namen.
Wie es weitergeht
Klassen, Objekte, Fehlerbehandlung mit try und catch und ein eigenes Projekt kommen in einem eigenen Folgemodul. Mit diesem Modul kannst du sie lesen, ohne in Panik zu geraten.
i <= namen.Length greift am Ende auf einen Index zu, den es nicht gibt. Und eine Methode, die ihr Ergebnis nur mit WriteLine ausgibt, liefert dem Aufrufer nichts zum Weiterrechnen.Auf deinem Rechner ausprobieren
Lege ein Array mit vier Ping-Zeiten in Millisekunden an. Schreibe eine Methode Mittelwert, die das Array bekommt und den Durchschnitt als double zurückgibt. Gib ihn aus.
Musterlösung ansehen
static double Mittelwert(int[] werte) { int summe = 0; foreach (int w in werte) { summe += w; } return (double)summe / werte.Length; } int[] ping = { 12, 15, 9, 14 }; Console.WriteLine(Mittelwert(ping));
Was nach den Grundlagen kommt
Kurze Einführungen, damit du weißt, was es gibt und wonach du suchen kannst.
Klassen und Objekte
Eine Klasse ist ein Bauplan, etwa für einen Router mit IP-Adresse und Status. Mit new entstehen daraus beliebig viele Objekte. Das ist das Kernthema des Folgemoduls.
Router r = new Router(); r.Ip = "10.0.0.1"; Console.WriteLine(r.Ip); class Router { public string Ip = ""; }
Fehler abfangen
Mit try und catch fängst du Laufzeitfehler ab, statt das Programm abstürzen zu lassen. TryParse aus Kapitel 6 ist die freundliche Variante für Eingaben.
try { int z = int.Parse("zwölf"); Console.WriteLine(z); } catch (FormatException) { Console.WriteLine("Bitte Ziffern verwenden."); }
Dictionary
Ein Dictionary speichert Paare aus Schlüssel und Wert, etwa Dienstname und Port. Nachschlagen per Schlüssel statt per Index.
Dictionary<string, int> ports = new Dictionary<string, int>(); ports["HTTPS"] = 443; ports["SSH"] = 22; Console.WriteLine(ports["SSH"]);
Namespaces und using
Ein Namespace sortiert Klassen wie ein Ordner. Console liegt in System. Neue Projekte binden die häufigsten Namespaces automatisch ein, darum siehst du in den Beispielen kein using System;.
NuGet
NuGet ist der Paketmanager von .NET. dotnet add package NAME holt eine Bibliothek ins Projekt. Vorher prüfen, wer sie pflegt: Fremdcode bleibt Fremdcode.
Visual Studio und VS Code
Visual Studio ist eine große Entwicklungsumgebung für Windows, VS Code ein leichter Editor mit C#-Erweiterung. Beide markieren Compilerfehler schon beim Tippen und haben einen Debugger, mit dem du ein Programm Zeile für Zeile ausführst.
.NET SDK und Projektstruktur
Ein Konsolenprojekt besteht im Kern aus Program.cs und einer .csproj-Datei mit den Einstellungen. Die Ordner bin und obj erzeugt der Build. Die gehören nicht ins Git, so wenig wie Passwörter in den Quelltext.
Quellen & Grenzen
Eigene Übungsaufgaben, keine offiziellen IHK-Aufgaben. Ausgaben sind für das Verhalten von C# unter .NET 8 geprüft. Kommazahlen erscheinen auf einem deutschen System mit Komma. Dieses Modul führt deinen Code nicht aus: Eigene Programme schreibst und startest du auf deinem Rechner.
Üben, bis es wehtut. Dann noch drei.
Alle Aufgaben werden zufällig erzeugt, dir geht der Stoff also nie aus. Nach jeder Antwort siehst du die Erklärung. Der Trainingsraum merkt sich, welche Aufgabentypen dir schwerfallen, und im Modus „Baustellen“ bekommst du genau die.
Welcher Begriff gehört zur Beschreibung?
Jede Zeile wird einzeln bewertet. Jede Zuordnung ist eine eigene Aufgabe.
Ernstfall. Ohne Netz und doppelten Boden.
Eine Probeprüfung im Stil der IHK: Aufgaben aus allen Themen, 30, 60 oder 90 Minuten, kein Hinweis, kein Nachschlagwerk. Du kannst zwischen den Aufgaben springen und Antworten ändern. Bewertet wird erst bei Abgabe, mit Note nach dem IHK-Punkteschlüssel und Auswertung pro Thema.
Wie lange willst du schwitzen?
Deine letzten Ergebnisse
Weniger Raten.
Mehr Kompilieren.
Wer Code lesen kann, muss Fehlermeldungen nicht mehr persönlich nehmen. Wenn der Lernpfad sitzt, zeig im Prüfungsmodus, was du kannst. Und wenn nicht: Die Baustellen warten schon auf dich.