I have always been interested in how to implement virtual methods and rewrite object-oriented languages. Although I know how to use the most basic design method, however, I have never found any detailed information to tell me how C # works.
There is nothing to read recently <essential. net> This book gave me a certain understanding of this matter (at least I think so ).
Because this problem involves method tables, I think we should first give a brief introduction to how to store objects in the memory. The following figure shows the storage of objects (from books ),
Suppose we have such a statement: Human B = new Human ();
The object reference is the declared variable B, which is a pointer and points to the Object where the object is actually stored (Human ). There are three main parts in this area. The first part is an index on this object. I still don't know the specific functions, but it is not used here, so you can ignore it. In the second part, htype is a pointer that stores information about the class to which the instance belongs. The third part is the data member that stores this class.
Here the focus is on the second pointer htype. The region to which htype points is called CORINFO_CLASS_STRUCT by the author. Each class has such a region and should be unique. In the CORINFO_CLASS_STRUCT area, you only need to know that there are three areas:
- There is a pointer to the CORINFO_CLASS_STRUCT area of the parent class, if there is a parent class.
- There is a pointer to the interface table. The interface table stores the htype of the inherited interface of this type.
- Method table
With the first two items, the relationship between the class and the class is established. The type conversion of the object is determined by this method, but we focus mainly on the method table.
To work with the problem description, I have defined two simple classes: Base and Child. Most of the methods in Base are virtual methods, and the same method is defined in Child, but the modifiers are different.
1 public class
2 {
3 static void Main ()
4 {
5 Base B = new Child ();
6 Child ch = new Child ();
7
8 B. print ();
9 B. print2 ();
10 B. print3 ();
11 B. print4 ();
12
13 ch. print ();
14 ch. print2 ();
15 ch. print3 ();
16 ch. print4 ();
17
18 Console. ReadKey ();
19}
20}
21
22 public class Base
23 {
24 public int x = 8;
25
26 public Base (){}
27
28
29 public void print ()
30 {
31 Writer. OutPut ("");
32}
33
34 public virtual void print2 ()
35 {
36 Writer. OutPut ("B ");
37}
38
39 public virtual void print3 ()
40 {
41 Writer. OutPut ("c ");
42}
43
44 public virtual void print4 ()
45 {
46 Writer. OutPut ("d ");
47}
48
49}
50
51 public class Child: Base
52 {
53 public Child (){}
54 public void print ()
55 {
56 Writer. OutPut ("e ");
57}
58
59 public override void print2 ()
60 {
61 Writer. OutPut ("f ");
62}
63 public new virtual void print3 ()
64 {
65 Writer. OutPut ("g ");
66}
67 public virtual void print4 ()
68 {
69 Writer. OutPut ("h ");
70}
71}
After this program is compiled into IL, let's take a look at the main method.
1. method private hidebysig static void Main () cel managed
2 {
3. entrypoint
4. maxstack 1
5. locals init (
6 [0] class FormatNumber. Base B,
7 [1] class FormatNumber. Child ch)
8 L_0000: nop
9 L_0001: newobj instance void FormatNumber. Child:. ctor ()
10 L_0006: stloc.0
11 L_0007: newobj instance void FormatNumber. Child:. ctor ()
12 L_000c: stloc.1