1. Create an object
The creation process of an object is mainly divided into two parts: memory allocation and initialization. In .NET, the memory area managed by CLR mainly consists of three parts: stack, GC heap, and LOH heap. The stack is mainly used to allocate value type data. Its management is controlled by the system, not by the GC like the GC heap. When the thread finishes executing the method of the value type instance, this space will be automatically released. Generally, the stack has high execution efficiency but limited capacity.
The GC heap is used to allocate small object instances. It is fully controlled by the GC to allocate and recycle memory. The LOH heap is prepared for large object instances. It will not be compressed and will only be recycled when the GC is fully recycled. In IL, you can see common instructions for creating objects such as newobj, ldstr (creating string objects), newarr (used to allocate new array objects), box (boxing), etc.
Of course, value types also exist on the heap. For example, when a value type is used as a field of a class, it will be stored in the instance object space in the heap, and when boxing, the value type will also exist on the heap. Okay, let's take a look at the memory allocation of creating an object. Now there is a Person class and Student class. Then this sentence Student s = new Student() { studentId = 2, Id = 4 }; After execution, the s object is created. Below I draw a picture to illustrate the memory allocation when creating an object, in which the s object also There are synchronized index blocks and type object pointers that I didn't draw.
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"); } }
View Code
2. The parent class object points to the subclass
We are writing In order to achieve polymorphism in programs, parent class objects are generally used to point to subclasses. Then when I write Person p=new Student();, a subclass object is created in the heap. The following is the memory allocation diagram of the parent class object pointing to the subclass. I added virtual methods and abstract methods in Person and overridden methods in Student subclass.
It can be seen from the figure that once the subclass overrides the virtual method or abstract method of the parent class, the two methods in the Person method table will be overridden by the subclass, and we can implement polymorphism based on it. . In addition, there is a new void Eat() method in the Student method table, but it cannot be called by p because new Eat() at this time belongs to a subclass.
That is to say, except for the overridden methods, p can only call methods in the Person method table. If it cannot be found, it will continue to search for methods of the Person parent class until object. Note that it will not look back, it will not look for methods in the Student method table
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. Point to the grandchild object
Now I will Add a Student subclass James. From the previous example, we already know that only the methods overridden by the override keyword will be called by the parent class, so I deleted all ordinary methods. The execution code is Person p = new James() { name = “James”, studentId = 2, Id = 4 }; The code and memory allocation diagram are as follows. In order to highlight the key points, I have not drawn the fields in the diagram. From the results, we can see that the SayHi method was finally overwritten by the SayHi of the grandchild class. From here, we can see the transitivity of inheritance!
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说:你好!"); } }
The above is the content of C# basic memory allocation. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!