In C#, wenn ich eine geerbte Klasse mit einem Standardkonstruktor habe, muss ich explizit den Konstruktor der Basisklasse aufrufen oder wird es implizit aufgerufen?In C#, müssen Sie den Basiskonstruktor aufrufen?
Antwort
Sie müssen den Basiskonstruktor nicht explizit aufrufen, er wird implizit aufgerufen.
Erweitern Sie Ihr Beispiel eine kleine und eine Konsole-Anwendung erstellen und Sie können dieses Verhalten für sich selbst überprüfen:
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass foo = new MyClass();
Console.ReadLine();
}
}
class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass constructor called.");
}
}
class MyClass : BaseClass
{
public MyClass()
{
Console.WriteLine("MyClass constructor called.");
}
}
}
AFAIK, Sie müssen nur den Basiskonstruktor aufrufen, wenn Sie irgendwelche Werte an ihn übergeben müssen.
Es ist impliziert.
Eine abgeleitete Klasse von der Basisklasse gebaut wird. Wenn Sie darüber nachdenken, muss das Basisobjekt im Speicher instanziiert werden, bevor die abgeleitete Klasse an es angehängt werden kann. Das Basisobjekt wird also auf dem Weg zum Erstellen des abgeleiteten Objekts erstellt. Also nein, Sie rufen den Konstruktor nicht auf.
Es ist impliziert, sofern es parameterlos ist. Dies liegt daran, Sie müssen Konstrukteure implementieren, die Werte annehmen, den Code für ein Beispiel siehe:
public class SuperClassEmptyCtor
{
public SuperClassEmptyCtor()
{
// Default Ctor
}
}
public class SubClassA : SuperClassEmptyCtor
{
// No Ctor's this is fine since we have
// a default (empty ctor in the base)
}
public class SuperClassCtor
{
public SuperClassCtor(string value)
{
// Default Ctor
}
}
public class SubClassB : SuperClassCtor
{
// This fails because we need to satisfy
// the ctor for the base class.
}
public class SubClassC : SuperClassCtor
{
public SubClassC(string value) : base(value)
{
// make it easy and pipe the params
// straight to the base!
}
}
Es impliziert für Basis parameterlos Bauer, aber es ist für die Ausfälle in der aktuellen Klasse benötigt:
public class BaseClass {
protected string X;
public BaseClass() {
this.X = "Foo";
}
}
public class MyClass : BaseClass
{
public MyClass()
// no ref to base needed
{
// initialise stuff
this.X = "bar";
}
public MyClass(int param1, string param2)
:this() // This is needed to hit the parameterless ..ctor
{
// this.X will be "bar"
}
public MyClass(string param1, int param2)
// :base() // can be implied
{
// this.X will be "foo"
}
}
Ein bisschen alt, um sicher zu sein, aber für den Fall, dass jemand darüber stolpert. Beachten Sie, dass die Aufrufreihenfolge in Ihrem überladenen Konstruktor tatsächlich lautet: base() -> MyClass() -> MyClass (int param1, string param2). Ihr Kommentar neben "this()" schien etwas irreführend, als würde das Hinzufügen von this() verhindern, dass der Aufruf die Basisklasse instanziiert. – Wrightboy
@Wrightboy Ja, das ist die richtige Reihenfolge, in der die Konstruktoren aufgerufen werden. Mein Punkt war nur, dass es nicht impliziert ist - Sie können 'this()' oder 'base()' explizit angeben, aber wenn Sie dies nicht tun, werden beide auch nicht aufgerufen. – Keith
'base()' wird immer aufgerufen. 'public MyClass (int param1, Zeichenfolge param2)' und 'public MyClass (int param1, Zeichenfolge param2): base()' sind äquivalent. Das 'this()' fügt einfach einen zusätzlichen Aufruf nach dem 'base()' Aufruf, aber vor sich selbst hinzu. – Wrightboy
Sie brauchen nicht den Basiskonstruktor nennen explizit wird es implizit genannt werden, aber manchmal müssen Sie Parameter an den Konstruktor in diesem Fall passieren Sie so etwas wie tun:
using System;
namespace StackOverflow.Examples
{
class Program
{
static void Main(string[] args)
{
NewClass foo = new NewClass("parameter1","parameter2");
Console.WriteLine(foo.GetUpperParameter());
Console.ReadKey();
}
}
interface IClass
{
string GetUpperParameter();
}
class BaseClass : IClass
{
private string parameter;
public BaseClass (string someParameter)
{
this.parameter = someParameter;
}
public string GetUpperParameter()
{
return this.parameter.ToUpper();
}
}
class NewClass : IClass
{
private BaseClass internalClass;
private string newParameter;
public NewClass (string someParameter, string newParameter)
{
this.internalClass = new BaseClass(someParameter);
this.newParameter = newParameter;
}
public string GetUpperParameter()
{
return this.internalClass.GetUpperParameter() + this.newParameter.ToUpper();
}
}
}
Hinweis: Wenn jemand eine bessere Lösung kennt, sagt mir bitte.
Sieht so aus, als ob jemand eine Lektion in Komposition gegen Vererbung braucht. ;) –
Dies ist korrekt, weil das OP "default (aka parameterless) Konstruktor" angegeben. –