Einleitung: Warum der Basisklassenkonstruktor nicht nur "langweilige Theorie" ist
\n\nStellen Sie sich vor, Sie bauen ein Haus. Sie haben ein Fundament (Basisklasse) und das Haus selbst (abgeleitete Klasse). Das Fundament ist bereits gelegt, aber damit das Haus stabil steht, müssen Sie es richtig mit dem Fundament "verbinden". In C# übernimmt diese "Verbindung" der Aufruf des Basisklassenkonstruktors über das Schlüsselwort base.
Dies ist eines der Themen, die tausende Fragen auf Stack Overflow verursachen. Warum? Weil Ihr Code ohne Verständnis dieses Mechanismus entweder nicht kompiliert oder unvorhersehbar funktioniert. In diesem Artikel behandeln wir den Aufruf des Basisklassenkonstruktors in C# vom Einfachen zum Komplexen: mit Beispielen, Fallstricken und realen Szenarien.
\n\nWas werden Sie in diesem Artikel lernen?
\n- \n
- Wie die Vererbung von Konstruktoren in C# funktioniert. \n
- Wann und warum Sie explizit
base()aufrufen müssen. \n - Wie Sie Parameter an den Basisklassenkonstruktor übergeben. \n
- Typische Fehler und wie Sie sie vermeiden. \n
- Fortgeschrittene Techniken: Konstruktorketten und Überladung. \n
1. Grundlagen: Was ist ein Basisklassenkonstruktor?
\n\nIn C# kann jede Klasse einen oder mehrere Konstruktoren haben. Wenn Sie eine Instanz einer abgeleiteten Klasse erstellen, wird zuerst der Konstruktor der Basisklasse aufgerufen. Dies stellt sicher, dass alle Felder und Eigenschaften des "Elternteils" initialisiert sind, bevor der "Nachkomme" seine Arbeit aufnimmt.
\n\nWenn Sie nicht explizit angeben, welcher Basisklassenkonstruktor aufgerufen werden soll, versucht der Compiler, den Standardkonstruktor (ohne Parameter) aufzurufen. Wenn dieser nicht vorhanden ist, erhalten Sie einen Kompilierungsfehler.
\n\nBeispiel 1: Impliziter Aufruf (ganz einfach)
\npublic class Animal\n{\n public string Name { get; set; }\n\n public Animal()\n {\n Name = "Unbekanntes Tier";\n Console.WriteLine("Animal: Konstruktor ohne Parameter");\n }\n}\n\npublic class Dog : Animal\n{\n public Dog()\n {\n Console.WriteLine("Dog: Konstruktor");\n }\n}\n\n// Verwendung\nDog dog = new Dog();\n// Ausgabe:\n// Animal: Konstruktor ohne Parameter\n// Dog: Konstruktor\n\nHier ruft Dog implizit Animal() auf. Das funktioniert, weil Animal einen Standardkonstruktor hat.
2. Problem: Wenn kein Standardkonstruktor vorhanden ist
\n\nStellen Sie sich nun vor, die Basisklasse erfordert obligatorische Parameter. Zum Beispiel muss ein Tier einen Namen haben. Wenn Sie den parameterlosen Konstruktor entfernen, wird der Code nicht mehr kompilieren.
\n\nBeispiel 2: Kompilierungsfehler
\npublic class Animal\n{\n public string Name { get; }\n\n public Animal(string name) // einziger Konstruktor\n {\n Name = name;\n }\n}\n\npublic class Dog : Animal\n{\n // Fehler CS7036: "Animal" enthält keinen Konstruktor, der 0 Argumente akzeptiert\n public Dog() \n {\n }\n}\n\nDer Compiler schreit: "Hey, ich weiß nicht, wie ich Animal ohne Namen initialisieren soll!". Die Lösung ist, den Basisklassenkonstruktor explizit mit base aufzurufen.
3. Das Schlüsselwort base: Expliziter Konstruktoraufruf
\n\nDas Schlüsselwort base in C# wird verwendet, um auf Member der Basisklasse zuzugreifen. Im Kontext von Konstruktoren ermöglicht es Ihnen anzugeben, welcher Konstruktor des Elternteils aufgerufen werden soll und mit welchen Argumenten.
Syntax:
\npublic class AbgeleiteteKlasse : BasisKlasse\n{\n public AbgeleiteteKlasse(Parameter) : base(Argumente)\n {\n // Konstruktorrumpf\n }\n}\n\nDer Doppelpunkt und base(Argumente) werden direkt nach der Konstruktorsignatur, vor dem Rumpf, platziert.
Beispiel 3: Fehler beheben
\npublic class Animal\n{\n public string Name { get; }\n\n public Animal(string name)\n {\n Name = name;\n Console.WriteLine($"Animal: {name} erstellt");\n