1. Ein Objekt erstellen
Der Erstellungsprozess eines Objekts ist hauptsächlich in zwei Teile unterteilt: Speicherzuweisung und Initialisierung. In .NET besteht der von CLR verwaltete Speicherbereich hauptsächlich aus drei Teilen: Stapel, GC-Heap und LOH-Heap. Der Stapel wird hauptsächlich zum Zuweisen von Werttypdaten verwendet. Seine Verwaltung wird vom System gesteuert, nicht vom GC wie beim GC-Heap. Wenn der Thread die Ausführung der Methode der Werttypinstanz beendet, wird dieser Speicherplatz automatisch freigegeben. Im Allgemeinen weist der Stapel eine hohe Ausführungseffizienz, aber eine begrenzte Kapazität auf.
Der GC-Heap wird zum Zuweisen kleiner Objektinstanzen verwendet. Er wird vollständig vom GC gesteuert, um Speicher zuzuweisen und wiederzuverwenden. Der LOH-Heap ist für große Objektinstanzen vorbereitet. Er wird nicht komprimiert und erst dann recycelt, wenn der GC vollständig recycelt ist. In IL können Sie allgemeine Anweisungen zum Erstellen von Objekten wie newobj, ldstr (Erstellen von Zeichenfolgenobjekten), newarr (zum Zuweisen neuer Array-Objekte), box (Boxen) usw. sehen.
Natürlich gibt es auch Werttypen auf dem Heap. Wenn ein Werttyp beispielsweise als Feld einer Klasse verwendet wird, wird er im Instanzobjektbereich im Heap gespeichert. Der Werttyp ist auch auf dem Heap vorhanden. Okay, werfen wir einen Blick auf die Speicherzuordnung beim Erstellen eines Objekts. Jetzt gibt es eine Person-Klasse und eine Student-Klasse. Dann wird dieser Satz Student s = new Student() { studentId = 2, Id = 4 }; Nach der Ausführung wird das s-Objekt erstellt. Unten zeichne ich ein Bild, um die Speicherzuordnung beim Erstellen eines Objekts zu veranschaulichen, in dem auch das s-Objekt enthalten ist Es gibt synchronisierte Indexblöcke und Typobjektzeiger, die ich nicht gezeichnet habe.
public class Person { public int Id; public void Eat() { Console.WriteLine("Eat Pear"); } } public class Student:Person { public int studentId; public void GotoSchool() { Console.WriteLine("Go to School"); } }
Code anzeigen
2. Das übergeordnete Klassenobjekt zeigt auf die Unterklasse
us Beim Schreiben eines Programms wird zum Erreichen von Polymorphismus im Allgemeinen das Objekt der übergeordneten Klasse verwendet, um auf die Unterklasse zu verweisen. Wenn ich dann Person p=new Student(); schreibe, wird im Heap ein Unterklassenobjekt erstellt. Das Folgende ist das Speicherzuordnungsdiagramm des übergeordneten Klassenobjekts, das auf die Unterklasse zeigt. Ich habe virtuelle Methoden und abstrakte Methoden in der Unterklasse „Person“ und überschriebene Methoden in der Unterklasse „Student“ hinzugefügt.
Wie aus dem Bild ersichtlich ist, werden die beiden Methoden in der Personenmethodentabelle von der Unterklasse überschrieben, sobald die Unterklasse die virtuelle Methode oder abstrakte Methode der übergeordneten Klasse überschreibt, und wir können Polymorphismus basierend implementieren darauf. Darüber hinaus gibt es in der Student-Methodentabelle eine neue void Eat()-Methode, die jedoch nicht von p aufgerufen werden kann, da new Eat() zu diesem Zeitpunkt zu einer Unterklasse gehört.
Das heißt, mit Ausnahme der überschriebenen Methode kann p nur die Methode in der Person-Methodentabelle aufrufen. Wenn sie nicht gefunden wird, wird bis zum Objekt weiter nach der Methode der übergeordneten Person-Klasse gesucht . Beachten Sie, dass es nicht zurückblickt und nicht nach der Methode in der Student-Methodentabelle sucht
public abstract class Person { public int Id; public void Eat() { Console.WriteLine( "在吃梨"); } public virtual void Walk() { Console.WriteLine("在散步"); } //抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。 public abstract void Run(); } public class Student:Person { public int studentId; public void GotoSchool() { Console.WriteLine("Go to School"); } public new void Eat() { Console.WriteLine("学生 吃苹果"); } public override void Walk() { Console.WriteLine("学生 在散步"); } public override void Run() { Console.WriteLine("学生 在跑步"); } }
3. Zeigen Sie auf das Enkelobjekt
Jetzt habe ich eine weitere James-Unterklasse von Student hinzugefügt. Aus dem vorherigen Beispiel wusste ich bereits, dass nur die mit dem Schlüsselwort override umgeschriebenen Methoden von der übergeordneten Klasse aufgerufen werden, also habe ich alle gewöhnlichen Methoden gelöscht. Der Ausführungscode lautet Person p = new James() { name = „James“, studentId = 2, Id = 4 }; Das Code- und Speicherzuordnungsdiagramm lautet wie folgt. Um die wichtigsten Punkte hervorzuheben, habe ich das nicht gezeichnet Felder im Diagramm. Aus den Ergebnissen können wir ersehen, dass die SayHi-Methode schließlich durch die SayHi-Methode des Enkelkindes überschrieben wurde. Von hier aus können wir die Transitivität der Vererbung erkennen!
public abstract class Person { public int Id; public virtual void Eat() { Console.WriteLine( "在吃梨"); } public virtual void Walk() { Console.WriteLine("在散步"); } //抽象方法只能在抽象类中声明,因此要在Person前加abstract,且只能声明并必须在子类中实现。 public abstract void Run(); public virtual void SayHi() { Console.WriteLine("人说:你好!"); } } public class Student:Person { public int studentId; public virtual void Eat() { Console.WriteLine("学生 在吃梨"); } public override void Walk() { Console.WriteLine("学生 在散步"); } public override void Run() { Console.WriteLine("学生 在跑步"); } } public class James:Student { public string name; public override void Eat() { Console.WriteLine("James 在吃梨"); } public override void Walk() { Console.WriteLine("James 在散步"); } public override void Run() { Console.WriteLine("James 在跑步"); } public override void SayHi() { Console.WriteLine("James说:你好!"); } }
Das Obige ist der Inhalt der grundlegenden Speicherzuweisung von C#. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn). )!