Referenztyp
Der Konstruktor ist eine spezielle Methode, um eine Instanz eines Typs in einen guten Zustand zu initialisieren. Beim Erstellen einer Instanz eines Referenztyps wird zunächst Speicher für die Datenfelder der Instanz zugewiesen. und dann die zusätzlichen Felder des Objekts (Typobjektzeiger und synchronisierter Blockindex) und ruft schließlich den Instanzkonstruktor des Typs auf, um den Initialisierungsstatus des Objekts festzulegen.
Beim Erstellen eines Referenztypobjekts wird der für das Objekt zugewiesene Speicher vor dem Instanzkonstruktor des Elektrophoresetyps immer auf 0 zurückgesetzt. Alle Felder, die vom Konstruktor nicht explizit überschrieben werden, erhalten garantiert 0 oder Null Werte. .
Im Gegensatz zu anderen Methoden kann der Stärkekonstruktor niemals vererbt werden, das heißt, die Klasse verfügt nur über den von der Klasse selbst definierten Glattkonstruktor. Da ein Instanzkonstruktor niemals vererbt werden kann, können die folgenden Modifikatoren nicht für einen Instanzkonstruktor verwendet werden: Virtual, New, Override, Sealed und Abstract. Wenn die Klasse keinen expliziten Konstruktor definiert, verwendet der C#-Compiler standardmäßig einen Parameterlosen Konstruktor. In seiner Implementierung ruft er einfach den Parameterlosen Konstruktor der Basisklasse auf.
Wenn der Modifikator der Klasse abstrakt ist, ist die Zugänglichkeit des vom Compiler generierten Standardkonstruktors Produkt; andernfalls erhält der Konstruktor das öffentliche Zugänglichkeitsattribut. Wenn die Basisklasse keinen parameterlosen Konstruktor bereitstellt, muss die abgeleitete Klasse explizit einen Basisklassenkonstruktor aufrufen, andernfalls meldet der Compiler einen Fehler. Wenn der Klassenmodifikator statisch (versiegelt und abstrakt) ist, generiert der Compiler überhaupt keinen Standardkonstruktor in der Klassendefinition.
Ein Typ kann mehrere Instanzkonstruktoren definieren. Jeder Konstruktor muss eine andere Signatur haben und jeder kann über unterschiedliche zugängliche Eigenschaften verfügen. Um den Code „überprüfbar“ zu machen, muss der Initialisierer der Klasse den Konstruktor der Basisklasse aufrufen, bevor er auf von der Basisklasse geerbte Felder zugreift. Wenn der abgeleitete Klassenkonstruktor nicht explizit einen Basisklassenkonstruktor aufruft, generiert der C#-Compiler automatisch einen Aufruf des Standardbasisklassenkonstruktors. Schließlich wird der öffentliche Konstruktor ohne Argumente von System.Object aufgerufen. Der Konstruktor tut nichts und gibt direkt zurück. Da System.Object keine Instanzdatenfelder hat, hat sein Konstruktor nichts zu tun.
In seltenen Fällen ist es möglich, eine Instanz eines Typs zu erstellen, ohne den Instanzkonstruktor aufzurufen. Ein typisches Beispiel ist die MemberwiseClone-Methode von Object. Diese Methode reserviert Speicher, initialisiert die zusätzlichen Felder des Objekts und kopiert dann die eigenen Daten des Quellobjekts in das neue Objekt. Darüber hinaus muss beim Deserialisieren eines Objekts mithilfe eines Laufzeitserialisierers nicht derselbe Prozess den Konstruktor aufrufen. Die Deserialisierung verwendet die Methode GetUnnitalizedObject oder GetSafeUninitailizedObject des Typs System.Runtime.Serialization.FormatterServices, um Speicher für das Objekt zu reservieren, und während des Prozesses wird kein Konstruktor aufgerufen.
Tipp:
Rufen Sie im Konstruktor keine virtuellen Methoden auf. Der Grund dafür ist, dass die Implementierung der virtuellen Methode durch den abgeleiteten Typ ausgeführt wird, wenn der instanziierte Typ die virtuelle Methode überschreibt. Zu diesem Zeitpunkt ist jedoch die Initialisierung aller Felder in der Vererbungshierarchie noch nicht abgeschlossen (der Konstruktor des instanziierten Typs). läuft noch nicht). Daher kann der Aufruf virtueller Methoden zu unvorhersehbarem Verhalten führen. Dies liegt letztlich daran, dass beim Aufruf einer virtuellen Methode der tatsächliche Typ, auf dem die Methode ausgeführt wird, erst zur Laufzeit ausgewählt wird.
Werttyp-Konstruktor (Struktur)
Der Werttyp-Konstruktor (Struktur) funktioniert völlig anders als der Referenztyp-Konstruktor (Klasse). Die CLR erlaubt immer die Erstellung von Instanzen von Werttypen, und es gibt keine Möglichkeit, die Instanziierung von Werttypen zu verhindern. Daher müssen Werttypen eigentlich keinen Konstruktor definieren, und der C#-Compiler integriert überhaupt keinen Standardkonstruktor ohne Argumente für Werttypen. Schauen wir uns den folgenden Code an:
internal struct Point {
public int m_x, m_y;
}
internal versiegelt class Reactangel
{
public Point m_TopLeft, m_bottomRight;
}
Um ein Rechteck zu konstruieren, müssen der neue Operator und der Konstruktor verwendet werden muss angegeben werden. In diesem Beispiel wird der vom C#-Compiler automatisch generierte Standardkonstruktor aufgerufen. Reservieren Sie Speicher für Reatangle, das zwei Instanzen des Point-Werttyps enthält. Aus Leistungsgründen ruft die CLR den Konstruktor nicht für jedes im Referenztyp enthaltene Werttypfeld auf. Wie bereits erwähnt, werden die Werttypfelder jedoch auf 0 oder null initialisiert.
Die CLR ermöglicht zwar die Definition von Konstruktoren für Werttypen, sie müssen jedoch explizit aufgerufen werden, damit sie ausgeführt werden können.
internal struct Point {
public int m_x, m_y;
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
}
interne versiegelte Klasse Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
this.m_TopLeft = new Point(1 ,2);
this.m_bottomRight = new Point(100,200);
}
}
Instanzkonstruktoren von Werttypen werden nur ausgeführt, wenn sie explizit aufgerufen werden. Wenn der Konstruktor von Rechteck daher nicht den neuen Operator verwendet, um den Konstruktor von Point aufzurufen, um die Felder m_TopLeft und m_bottomRight von Reatangle zu initialisieren, sind die Felder m_x und m_y in beiden Punktfeldern 0.
Neu schreiben der obige Code:
internal struct Point {
public int m_x, m_y;
public Point()
{
m_x = 5;
m_y = 6;
}
}
interne versiegelte Klasse Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
}
}
Wie stark werden nun beim Erstellen einer neuen Rechteckklasse die Felder m_x und m_y in den beiden Punktfeldern initialisiert? Ist es 0 oder 5?
Vielleicht denken Sie, dass der C#-Compiler Code im Konstruktor von Reactangel generiert und automatisch Points Standardkonstruktor ohne Argumente für die beiden Felder von Reactangel aufruft. Um die Laufzeitleistung Ihrer Anwendung zu verbessern, generiert der C#-Compiler solchen Code jedoch nicht automatisch. Selbst wenn ein Werttyp einen Konstruktor ohne Parameter bereitstellt, generieren viele Compiler niemals Code, um ihn aufzurufen. Um einen Konstruktor ohne Parameter für den Werttyp zu implementieren, muss der Entwickler Code hinzufügen, der den Konstruktor für den Werttyp explizit aufruft. Aber werden die beiden Felder von Point' aus diesem Grund auf 0 initialisiert? Das Ergebnis ist:
Der C#-Compiler lässt bewusst nicht zu, dass Werttypen Parameterlose Konstruktoren definieren, um dies zu ermöglichen verhindern Entwickler sind verwirrt darüber, wann dieser Konstruktor aufgerufen wird. Da ein Parameterloser Konstruktor nicht definiert werden kann, generiert der Compiler niemals Code, der ihn automatisch aufruft. Ohne einen Parameterlosen Konstruktor werden Felder von Werttypen immer auf 0 oder Null initialisiert.
Typkonstruktor:
wird auch als statischer Konstruktor, Klassenkonstruktor oder Typinitialisierer bezeichnet. Typkonstruktoren können mit Referenztypen und Werttypen verwendet werden. Der Zweck eines Instanzkonstruktors besteht darin, den Anfangszustand einer Instanz eines Typs festzulegen. Dementsprechend besteht die Rolle des Typkonstruktors darin, den Anfangszustand des Typs festzulegen. Der Typ definiert standardmäßig keinen Typkonstruktor. Wenn er definiert ist, kann es nur einen geben. Darüber hinaus verfügen Typkonstruktoren niemals über Parameter.
interne versiegelte Klasse SomeRefType {
statische SomeRefType()
{
//Beim ersten Besuch führen Sie den Code hier aus
}
}
interne Struktur SomeValType
{
statische SomeValType()
{
//Beim ersten Besuch führen Sie den Code hier aus
}
}
Es ist ersichtlich, dass die Definition eines Typkonstruktors ähnlich ist zum Definieren eines parameterlosen Instanzkonstruktors. Der Unterschied besteht darin, dass er als statisch markiert sein muss. Darüber hinaus sind Typkonstruktoren immer privat. Der Grund dafür, dass es privat ist, besteht darin, zu verhindern, dass Entwickler Code schreiben, um es aufzurufen, und die CLR ist immer für seine Aufrufe verantwortlich.
Tipp:
Obwohl Sie einen Typkonstruktor in einem Werttyp definieren können, sollten Sie dies eigentlich nie tun, da die CLR manchmal den statischen Konstruktor des Werttyps nicht aufruft: zum Beispiel
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("Dieser Satz wird nie angezeigt" ). ( string[] args)
{
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x);
Console.ReadKey();
}
}
Der Code des Typs Nur Konstruktor Kann auf die statischen Felder eines Typs zugreifen und seine unkonventionelle Verwendung besteht darin, diese Felder zu initialisieren.
Das obige ist der detaillierte Inhalt vonWas ist ein Konstruktor? Was ist der Referenztyp?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!