Klassen & Objekte
Klassen definieren, Objekte erzeugen, Konstruktoren, Properties und Methoden. Das Fundament der Objektorientierung in C#.
Inhaltsverzeichnis
Klassen & Objekte
Klassen sind Bauplรคne fuer Objekte. Ein Objekt ist eine konkrete Instanz einer Klasse - mit eigenen Daten und Verhalten.
Eine einfache Klasse
public class Person
{
public string Name;
public int Alter;
public void Vorstellen()
{
Console.WriteLine($"Hallo, ich bin {Name} und {Alter} Jahre alt.");
}
}
publicmacht die Klasse oeffentlich sichtbarNameundAltersind Felder (Daten)Vorstellenist eine Methode (Verhalten)
Ein Objekt erzeugen
var anna = new Person();
anna.Name = "Anna";
anna.Alter = 28;
anna.Vorstellen(); // "Hallo, ich bin Anna und 28 Jahre alt."
Mit Object Initializer (kuerzer):
var anna = new Person { Name = "Anna", Alter = 28 };
Properties statt Felder
Oeffentliche Felder sind unsicher - jeder kann sie beliebig aendern. Properties erlauben Kontrolle:
public class Person
{
public string Name { get; set; }
public int Alter { get; set; }
}
Das sind Auto-Properties - der Compiler generiert Getter und Setter fuer dich.
Nutzen wie Felder
anna.Name = "Anna"; // Setter wird aufgerufen
var n = anna.Name; // Getter wird aufgerufen
Read-Only Properties
public string Name { get; } // nur im Konstruktor setzbar
public string Name { get; init; } // nur bei Initialisierung setzbar (modern)
public string Name { get; private set; } // intern setzbar, aussen read-only
init ist besonders nuetzlich:
public class Person
{
public string Name { get; init; }
public int Alter { get; init; }
}
var p = new Person { Name = "Anna", Alter = 28 };
// p.Name = "Max"; // FEHLER - init erlaubt es nur bei Initialisierung
Properties mit Validierung
public class Person
{
private int _alter;
public int Alter
{
get => _alter;
set
{
if (value < 0)
throw new ArgumentException("Alter kann nicht negativ sein");
_alter = value;
}
}
}
value ist der uebergebene Wert im Setter.
Konstruktoren
Der Konstruktor wird beim Erstellen aufgerufen:
public class Person
{
public string Name { get; init; }
public int Alter { get; init; }
public Person(string name, int alter)
{
Name = name;
Alter = alter;
}
}
var anna = new Person("Anna", 28);
Du kannst mehrere Konstruktoren haben (Overloading):
public Person() { Name = "Unbekannt"; }
public Person(string name) { Name = name; }
public Person(string name, int alter) { Name = name; Alter = alter; }
Und sie koennen sich gegenseitig aufrufen mit : this(...):
public Person() : this("Unbekannt", 0) { }
public Person(string name) : this(name, 0) { }
public Person(string name, int alter)
{
Name = name;
Alter = alter;
}
Private Felder und Methoden
private (Default) ist nur innerhalb der Klasse sichtbar. Nutze Konvention _feldname:
public class BankKonto
{
private decimal _saldo;
public decimal Saldo => _saldo; // read-only Property
public void Einzahlen(decimal betrag)
{
if (betrag <= 0) throw new ArgumentException("Betrag muss positiv sein");
_saldo += betrag;
}
public bool Auszahlen(decimal betrag)
{
if (betrag <= 0 || betrag > _saldo) return false;
_saldo -= betrag;
return true;
}
}
Zugriffsmodifizierer
| Modifier | Sichtbar |
|---|---|
public | Ueberall |
private | Nur in der Klasse (Default) |
protected | In Klasse + Subklassen |
internal | In der gleichen Assembly |
protected internal | Subklassen oder gleiche Assembly |
private protected | Subklassen in der gleichen Assembly |
90% der Zeit reicht public und private.
this
this ist die aktuelle Instanz. Wird gebraucht, wenn Parameternamen Felder verdecken:
public class Person
{
private string name;
public Person(string name)
{
this.name = name; // this-Feld vs. Parameter
}
}
static Members
static gehoert zur Klasse, nicht zu einem Objekt:
public class Person
{
public static int Anzahl { get; private set; } = 0;
public string Name { get; }
public Person(string name)
{
Name = name;
Anzahl++;
}
}
var a = new Person("Anna");
var b = new Person("Max");
Console.WriteLine(Person.Anzahl); // 2
Aufruf ueber den Klassennamen, nicht das Objekt.
Records - kurze Datenklassen
Fuer reine Daten-Container gibt es record:
public record Person(string Name, int Alter);
Das ist ein kompletter, unveraenderlicher Datentyp mit:
- Konstruktor
init-Properties- Einem sinnvollen
ToString - Wertbasierter Gleichheit (
a == bvergleicht Werte, nicht Referenzen) with-Expression fuer Kopien mit Aenderungen
var anna = new Person("Anna", 28);
var anna29 = anna with { Alter = 29 }; // Kopie mit Aenderung
Console.WriteLine(anna); // Person { Name = Anna, Alter = 28 }
Console.WriteLine(anna == anna29); // False
Records sind perfekt fuer DTOs und Value Objects.
Methoden mit eigenem Status
public class Zaehler
{
private int _count = 0;
public void Hoch() => _count++;
public void Runter() => _count--;
public int Wert => _count;
}
var z = new Zaehler();
z.Hoch();
z.Hoch();
z.Runter();
Console.WriteLine(z.Wert); // 1
Zusammenfassung
- Klassen beschreiben Daten (Felder/Properties) und Verhalten (Methoden)
newerzeugt Instanzen- Auto-Properties:
public string Name { get; set; } initfuer unveraenderliche Objekte- Konstruktoren initialisieren Objekte
staticfuer Klassen-weite Daten und Methodenrecordist die kurze Form fuer Daten-Container
Im naechsten Kapitel: Vererbung und Interfaces.