For the method call, it is my headache, what static method, instance method, instance virtual method, here to check a lot of information, summarized as follows:
This statement, I am also a rookie, here only to discuss the method of call related technology, belonging to personal understanding, if there are errors, please correct me
Ideas:
1 How does the CLR build the method table as it loads the type?
2 How do I determine which type of method table to use when the program calls the method?
3 How do I determine the location of a method in a method table when the program calls the method (the first method in the method table)?
The order in which the method is arranged in the method table:
Inherited instance virtual method, instance virtual method, constructor function, static method, instance method
Method Table Arrangement Principle:
1 during the construction of a method table of a class: The virtual method is always copied in the method table of the subclass, and other methods, such as instance methods, constructors, static methods, are not inherited in the method table of the subclass.
2 in the method table of the class: The virtual method is always at the beginning of the method table; The inherited virtual method is first, and the new virtual method is immediately followed ()
3 The virtual method is followed by a constructor, a static method, an instance method.
Why put "inherited instance virtual methods" and "instance virtual methods" at the beginning of the method table?
In this case, the location of each virtual method in the method table of the related class is constant (whether it is in the class in which the method was created or in the derived class): For example, if the order of a virtual method in a class is K, then the position in the subclass or parent class (if there is this method in the parent class) is K.
If a new virtual method is added to a subclass, because the virtual method in the parent class's method table has been copied to the front of the method table of the child class before the new virtual method is filled, the position ordinal of all the methods in the parent class in its subclass is constant.
If new methods (instance methods, constructors, static methods, and so on) are added to the subclass in addition to the virtual method, these methods are all in the same row after the virtual method
The above two points guarantee that the virtual method is invariant in its own class, parent class, subclass, and its position in the method table (the first of the method tables).
Conclusion: The ordering of virtual methods in the method table can maintain the hierarchy structure of virtual methods in the hierarchy of classes, which is the basis of realizing polymorphism, that is, why inheritance is the basis of realizing polymorphism.
Example:
The definition code for the class is as follows:
classProgram {Static voidMain (string[] args) {Father son=NewSon (); Son. DoWork (); Son. Dovirtualwork (); Son. Dovirtualall (); Son.dostaticwork (); Father Agrandson=Newgrandson (); Agrandson.dowork (); Agrandson.dovirtualwork (); Agrandson.dovirtualall (); Console.readkey (); } } Public classFather { Public voidDoWork () {Console.WriteLine ("father.dowork ()"); } Public Virtual voidDovirtualwork () {Console.WriteLine ("father.dovirtualwork ()"); } Public Virtual voidDovirtualall () {Console.WriteLine ("Father.dovirtualall ()"); } } Public classSon:father { Public Static voidDostaticwork () {Console.WriteLine ("son.dostaticwork ()"); } Public New voidDoWork () {Console.WriteLine ("son.dowork ()"); } Public New Virtual voidDovirtualwork () {Console.WriteLine ("son.dovirtualwork ()"); } Public Override voidDovirtualall () {Console.WriteLine ("Son.dovirtualall ()"); } } Public classGrandson:son { Public Override voidDovirtualwork () {Console.WriteLine ("grandson.dovirtualwork ()"); } Public Override voidDovirtualall () {Console.WriteLine ("Grandson.dovirtualall ()"); } } Public classGrandgrandson:grandson { Public New Virtual voidDovirtualwork () {Console.WriteLine ("ggson.dovirtualwork ()"); } Public Override voidDovirtualall () {Console.WriteLine ("Ggson.dovirtualall ()"); } }
Sample Code
Entry Methodde JIT name6751cd88 672360BC prejit System.Object.ToString () 67516a90 672360c4 Prejit System.Object.Equals ( System.Object)67516660 672360e4 prejit System.Object.GetHashCode () 675967c0 672360f8 Prejit System.Object.Finalize () 003201c8 001d3824 JIT MethodInvoke.Father.DoVirtualWork () 001dc035 001d382c NONE MethodInvoke.Father.DoVirtualAll ()00320158 001d3834 JIT methodinvoke.father. ctor ()00320190 001d3818 JIT MethodInvoke.Father.DoWork ()
method table for the Father class
Entry methodde JIT name6751cd88 672360BC prejit System.Object.ToString () 67516a90 672360c4 Prejit System.obje Ct. Equals (System.Object)67516660672360e4 Prejit System.Object.GetHashCode () 675967c0 672360f8 Prejit System.Object.Finalize ()////Top four methods are inherited from the object class003201c8 001d3824 JIT MethodInvoke.Father.DoVirtualWork ()00320200001d38b8 JIT MethodInvoke.Son.DoVirtualAll ()//This is also the virtual method of the inherited Father class, except that the method overridden in the son class overrides the//These two classes are methods that inherit from the Father class001dc059 001d38b0 NONE MethodInvoke.Son.DoVirtualWork ()//This is the new method in the son class.00320120001d38c0 JIT Methodinvoke.son. ctor ()//the constructor of the son class00320238001d3898 JIT MethodInvoke.Son.DoStaticWork ()//static method of son class001dc055 001d38a4 NONE MethodInvoke.Son.DoWork ()//instance method of son class
Method table for son class
Entry methodde JIT name6751cd88 672360BC prejit System.Object.ToString () 67516a90 672360c4 Prejit System.Object.Equals (System.Object)67516660 672360e4 prejit System.Object.GetHashCode () 675967c0 672360f8 Prejit System.Object.Finalize () 003201c8 001d3824 JIT MethodInvoke.Father.DoVirtualWork () 003202a8 001d3930 JIT MethodInvoke.Grandson.DoVirtualAll () 001dc079 001d3928 NONE MethodInvoke.Grandson.DoVirtualWork ()00320270 001d3938 JIT Methodinvoke.grandson. ctor ()
method table for the grandson class
Determination of methods in the method table:
1 The simplest is a non-virtual method
There is only one case in which the method is defined in that class. Because of these non-virtual methods, they do not replicate their methods in their subclasses. The last two methods in the method table of the Son class
MethodInvoke.Son.DoStaticWork () MethodInvoke.Son.DoWork () These two classes are defined in the son class, so there are only two methods in the method table of the son class.
That is the proof of the argument.
2 for virtual methods
There are three possible sources of methods in the method table
A new virtual method from its class, which adds a method table slot (using the new virtual and virtual keywords) in the appropriate location in the method table
For example: public new virtual void dovirtualwork () and public virtual void Newmethod ()
B by inheriting the parent class and redefining the virtual method in the class, when the method of the parent class is copied to the method table of the class, it is overwritten with a redefined method, and the method table slot is not created (using the override keyword)
For example: public override void Dovirtualwork ()
C by inheriting the virtual method of the parent class, which does not use any keywords, he simply copies the method of the parent class to the method table of the class.
b c both inherit the position of the method in the method table in the parent class, and a adds a new location in the method table of the class (new method table slot is seen)
Iii. invocation of the method:
To understand the invocation of a method, first explain a few nouns (the nouns you understand).
Reference variable: Refers to the variable at the time of declaration, such as object A, where a is a reference variable
Object, instance: the object created in the instantiation, such as new object (), creates an object (and returns a reference to an object)
From C # to IL:
First look at how the C # compiler translates from the C # language to the Il language.
When invoking a method, the C # compiler is concerned with the type of the reference variable, and it does not care what the instance type is. The C # compiler starts from the type of reference variable to its parent class by layer:
A For the instance virtual method, the call to the method is translated until the virtual keyword is found . Such as:
For the type in the above code, if I have code father gd=new grandson (); GD. Dovirtualwork (), then in Il translates into Callvirt/call Father::D ovirtualwork ()
If there is code grandson gd=new grandson (); GD. Dovirtualwork (), then in Il it translates into callvirt/call Son::D ovirtualwork ()
This is usually the case with callvirt, but in some cases, call is used:
-for example, a virtual method referenced by a sealed class can be called, because it can be determined that there are no derived classes, the methods in the derived class are not invoked, and call can avoid type checking and improve performance
-Call is also used when a value type calls a virtual method, the value type is first a sealed type, and the second call can prevent the value type from being boxed
-When calling the virtual method of the base class in the type definition, call avoids the stack overflow caused by the callvirt recursive call itself, as
class call_callvirt{ publicoverridebool Equals (object obj) { return Base . Equals (obj); } }
Call base class virtual method
b for a non-virtual method, the method is called until it finds the first defined class that contains the method . Such as:
For the type in the above code, if I have code father gd=new grandson (); GD. DoWork (), then in Il translates into call/callvirt Father::D owork ()
If there is code grandson gd=new grandson (); GD. DoWork (), then in Il it translates into call/callvirt Son::D ovirtualwork ()
The use of call is usually used here, but there are also cases where callvirt is used:
-Common use of callvirt in reference types, because the reference variable is null when an exception NullReferenceException is thrown, and call does not throw any exceptions, and call callvirt in C # for type safety to complete a non-virtual type invocation
In general, the invocation of a method in C # is basically translated into call/callvirt (and calli I seldom see in C #) instruction call method, although the call and callvirt usage is messy, but the bones still have a difference:
Call is used to invoke a method of a static type, declaring a type, and callvirt calls a method of a dynamic type, an actual (instance) type
From Il to Localcode
The first thing to say here is the difference between call and callvirt in IL:
Call calls the function directly (as the previous part knows, the function called here is determined by the type of the reference variable);
Perform a static dispatch: You can determine the action it performs during compilation ( you can determine which type of method table to use when compiling )
callvirt checks the type of the instance to which the reference variable is pointing (including whether it is a null reference), and calls the corresponding location in the method table of the instance's type (this command actually means knowing the location of the method in the method table, The method by which the type of the instance determines the corresponding location in the method table used
Perform dynamic scheduling: At run time, you can determine which action to perform (requires runtime to determine the type of instance to which the reference variable points, and then determine the method table for that instance type to be used )
Another method call:
Based on the dynamic scheduling mechanism of reflection technology, the basic principle is to look up the information of the method table to implement the invocation mode at run time. Common ways are: Methodinfo.invoke () mode and dynamic method delegate (Delegate) mode.
Iv. the results of the code posted are as follows:
Answer the question:
It is assumed that there are three types of ABC, and A<--B<--C
1 How does the CLR build the method table as it loads the type?
Here only the method table is concerned, other parts of the class are ignored: The CLR needs to load the type before it instantiates an instance of the type:
Load object class (if not yet loaded, same as below);
Then load Class A, in this process, the virtual method of the object class is copied in the Class A method table, and then arrange the virtual method of Class A, constructor, static method, instance method;
Then load Class B, in this process, the virtual method of Class A is copied in the method table of Class A, then the virtual method of Class B, the constructor, the static method, and the instance method are arranged sequentially.
Then load Class C, in this process, the virtual method of Class B is copied in the method table of Class C, then the virtual method of Class C, constructor, static method and instance method are arranged.
..... And so on, this constitutes the various classes of their own method table, the method table includes inherited virtual methods, virtual methods, constructors, static methods, instance methods
2 How do I determine which type of method table to use when the program calls the method?
For non-virtual methods: What type of reference variable is used, and which type of method table to use
For virtual methods: What type of object type the reference variable refers to, and which type of method table to use
3 How do I determine the location of a method in a method table when the program calls the method (the first method in the method table)?
The position of the method in the method table that refers to the variable type (because of the nature of the virtual method table, which determines the location of the virtual method is the same in the method table of each class in the class hierarchy, that is, the location of the virtual method is inherited by its subclasses)
Finish
PostScript : This article looked up online a lot of cattle people's blog, and reference to the "you must know. Net" Wang Tao and other information, thanks to these cattle people's hard work results, write their own to know hard-won AH. As the author first wrote, there are many shortcomings, I hope to correct
Method table creation and invocation of method for C # class