EMZETT.
Login

Kurz: Eine Klasse bündelt Daten und Verhalten. Von ihr erzeugst du Objekte mit new.

Teil des Kurses C#

Kapitel 7 von 16 im Kurs C# (Abschnitt „Objektorientierung“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Eine Klasse bündelt Daten und Verhalten. Von ihr erzeugst du Objekte mit new.

var rex = new Hund("Rex", 3);
var mimi = new Hund("Mimi", 5) { Rasse = "Siamkatze" };      // Objekt-Initialisierer
rex.Geburtstag();
Console.WriteLine(rex.Bellen());
Console.WriteLine($"{rex} | {mimi.Rasse} | {rex.Alter}");
 
class Hund
{
    public string Name { get; }                              // nur lesbar (Eigenschaft)
    public int Alter { get; private set; }                   // von außen nur lesbar
    public string Rasse { get; set; } = "unbekannt";         // lesen und schreiben, mit Standardwert
 
    public Hund(string name, int alter)                      // Konstruktor
    {
        Name = name;
        Alter = alter;
    }
 
    public void Geburtstag() => Alter++;
    public string Bellen() => $"{Name} sagt: Wuff!";
    public override string ToString() => $"Hund[{Name}, {Alter}]";
}

Ausgabe:

Rex sagt: Wuff!
Hund[Rex, 4] | Siamkatze | 4

Eigenschaften (Properties)

Eigenschaften sehen wie Felder aus, laufen aber über get/set und erlauben Prüfungen:

var k = new Konto("Mia");
k.Einzahlen(100);
k.Einzahlen(50);
Console.WriteLine($"{k.Inhaber}: {k.Stand}");
try { k.Einzahlen(-5); } catch (ArgumentException e) { Console.WriteLine("Fehler: " + e.Message); }
k.Limit = 200;
Console.WriteLine($"{k.Limit} {k.IstImPlus}");
 
class Konto
{
    private decimal _stand;                                 // privates Feld
 
    public string Inhaber { get; }
    public decimal Stand => _stand;                         // berechnet/nur lesbar
    public bool IstImPlus => _stand > 0;
    public decimal Limit
    {
        get => _limit;
        set => _limit = value >= 0 ? value : throw new ArgumentOutOfRangeException(nameof(value));
    }
    private decimal _limit;
 
    public Konto(string inhaber) => Inhaber = inhaber;
 
    public void Einzahlen(decimal betrag)
    {
        if (betrag <= 0) throw new ArgumentException("Betrag muss positiv sein", nameof(betrag));
        _stand += betrag;
    }
}

Ausgabe:

Mia: 150
Fehler: Betrag muss positiv sein (Parameter 'betrag')
200 True

Auto-Eigenschaften ({ get; set; }) legen das Feld selbst an. init erlaubt Zuweisung nur bei der Erzeugung, required erzwingt sie.

var p = new Person { Name = "Mia", Alter = 17 };
Console.WriteLine($"{p.Name} {p.Alter}");
// p.Name = "Tom";     // Fehler: init-only
 
class Person
{
    public required string Name { get; init; }               // Pflicht beim Erzeugen, danach unveränderlich
    public int Alter { get; init; }
}

Ausgabe:

Mia 17

static, this, Konstanten

Console.WriteLine(Mathe.Quadrat(7) + " " + Mathe.Pi);
var a = new Zaehler(); var b = new Zaehler();
Console.WriteLine(Zaehler.Anzahl);
 
static class Mathe                                          // nur statische Member
{
    public const double Pi = 3.14159;
    public static int Quadrat(int x) => x * x;
}
class Zaehler
{
    public static int Anzahl { get; private set; }
    public Zaehler() => Anzahl++;
}

Ausgabe:

49 3.14159
2

Sichtbarkeit

ModifikatorSichtbar für
publicalle
privatenur die Klasse (Standard bei Membern)
protectedKlasse und Unterklassen
internaldasselbe Projekt (Assembly)
protected internal, private protectedKombinationen
filenur diese Datei (C# 11)

Konstruktoren

Console.WriteLine(new Punkt().ToString() + new Punkt(3).ToString() + new Punkt(3, 4));
Console.WriteLine(new Linie(new Punkt(0, 0), new Punkt(3, 4)).Laenge);
 
class Punkt
{
    public double X { get; }
    public double Y { get; }
    public Punkt() : this(0, 0) { }                          // Konstruktoren verketten
    public Punkt(double x) : this(x, 0) { }
    public Punkt(double x, double y) { X = x; Y = y; }
    public override string ToString() => $"({X}|{Y})";
}
 
// Primärkonstruktor (C# 12)
class Linie(Punkt start, Punkt ende)
{
    public double Laenge => Math.Sqrt(Math.Pow(ende.X - start.X, 2) + Math.Pow(ende.Y - start.Y, 2));
}

Ausgabe:

(0|0)(3|0)(3|4)
5

Finalizer, IDisposable und using

Der Garbage Collector verwaltet den Speicher. Für Ressourcen (Dateien, Verbindungen) implementierst du IDisposable und nutzt using:

using (var r = new Ressource("A"))
{
    r.Arbeiten();
}
using var b = new Ressource("B");                             // wird am Ende des Blocks geschlossen
b.Arbeiten();
Console.WriteLine("Ende");
 
class Ressource : IDisposable
{
    private readonly string _name;
    public Ressource(string name) { _name = name; Console.WriteLine($"öffne {_name}"); }
    public void Arbeiten() => Console.WriteLine($"{_name} arbeitet");
    public void Dispose() => Console.WriteLine($"schließe {_name}");
}

Ausgabe:

öffne A
A arbeitet
schließe A
öffne B
B arbeitet
Ende
schließe B

Merke

  • Klasse: Felder, Eigenschaften (get/set/init), Methoden, Konstruktoren
  • private set, init und required steuern Veränderbarkeit
  • static gehört zur Klasse; const ist eine Compile-Zeit-Konstante
  • Konstruktoren lassen sich verketten (: this(...)); Primärkonstruktoren seit C# 12
  • IDisposable + using räumen Ressourcen deterministisch auf

Übungsaufgabe

Schreibe eine Klasse Rechteck mit Eigenschaften Breite und Höhe (Prüfung > 0), einer berechneten Eigenschaft Flaeche und ToString.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Arrays und Collections

Weiter: Vererbung, Interfaces und Polymorphie

Alle Kapitel: C# im Überblick