The "method signature" includes the return type, method name, and parameter list, which jointly identify a method.
The "declaration method" indicates the signature of the method. "Define method" is the code that is executed when the method is called.
A method with the same name indicates two methods with the same signature.
"Override" A method means that the subclass wants to inherit the declaration of the parent class on the method, but wants to redefine the method.
When the word "use" is used separately, it can be "Explicit" or "implicit": the former is specified in the Code, and the latter is inferred based on the context of the statement.
Methods of a class include methods defined in the class and methods of the direct parent class obtained by inheritance. Pay attention to the recursive nature of this rule.
Theory
In the parent class and subclass, apart from the inheritance chain between classes, there is also an inheritance chain between methods.
In C #, when a method is declared in a class, there are four key words related to method inheritance: new, virtual, sealed, and override.
Virtual indicates that the method with the same name of the subclass is allowed to establish an inheritance chain with ①.
Override indicates that ① An inheritance chain is established between the method with the same name as the parent class, and the virtual keyword is used implicitly.
New indicates that it has cut off the inheritance chain between method ① and method of the parent class with the same name.
Sealed indicates that it establishes an inheritance chain (note that this is the feature of the override keyword) with the method of the same name as the parent class, and does not allow the method of the same name of the subclass to establish an inheritance chain with it. When using the sealed keyword, the override keyword must be explicitly used at the same time.
And:
If you do not use the above keywords when defining a method, the method will have the New Keyword feature. For this, if the parent class does not have a method of the same name, there is no impact; if the parent class has a method of the same name, the compiler will give a warning, ask if you want to hide the method with the same name as the parent class, and we recommend that you explicitly specify the New Keyword for it.
① It refers to the method being declared.
According to the preceding instructions, when calling a method in a class, one or more "method inheritance chains" can be constructed for this method ". First, list the class inheritance chains from subclass ② to parent class ③, and list the initial or redefinition of these classes for this method. Then, from the parent class to the Child class, check the definition of the method for each class one by one, and construct the method inheritance chain according to the following rules:
Any method definition that does not use the override or sealed keyword will become the beginning of the inheritance chain;
If this class uses the virtual keyword when defining the method, It will be appended to the inheritance chain.
The end of the inheritance chain depends on two factors: if a method with the same name as the New Keyword exists in the subclass, the previous inheritance chain ends immediately (this method will not be added to the inheritance chain ); if a method with the same name using the sealed keyword exists in the subclass, add the method to the inheritance chain and end the inheritance chain.
When you get an instance of subclass ②, but use the object reference of parent class ③ to call a method (for example, "A instanceref = new C (); instanceref. foo1 () ", then the reference of type A points to the object of type C), C # first checks whether the method is a virtual method (using the virtual keyword ): if not, simply call the parent class ③ version of the method. If yes, search for the method along the inheritance chain of the method and find the method at the bottom of the inheritance chain.
② Subclass: the actual type of the instance.
③ Parent class: refers to the type referenced by the object when the method is called. This type must be the parent type of the subclass.
Practice
I have defined the following four classes:
Class Definition
Public Class
{
Public Virtual void foo1 ()
{
Console. writeline ("A. foo1 () was invoked .");
}
Public void foo2 ()
{
Console. writeline ("A. foo2 () was invoked .");
}
}
Public Class B:
{
Public override void foo1 ()
{
Console. writeline ("B. foo1 () was invoked .");
}
Public new virtual void foo2 ()
{
Console. writeline ("B. foo2 () was invoked ");
}
}
Public Class C: B
{
Public new void foo1 ()
{
Console. writeline ("C. foo1 () was invoked .");
}
}
Public Class D: c
{
Public override sealed void foo2 ()
{
Console. writeline ("D. foo2 () was invoked .");
}
}
What will be printed when the following code is run?
Run the code
C ad = new D ();
A ac = new C ();
Ad. foo1 ();
Ad. foo2 ();
AC. foo1 ();
AC. foo2 ();
The result is:
Output result
C. foo1 () was invoked.
D. foo2 () was invoked.
B. foo1 () was invoked.
A. foo2 () was invoked.
The example is very simple. According to the previous rules, you can draw the following picture. In the figure, the ends of the circle indicate closed and interrupted inheritance chains; the ends of the diamond indicate open and allow the construction of inheritance chains; equations in the class description, indicates where the actual executed code body (normal font on the right of the equal sign) is defined when the corresponding method (italic on the left of the equal sign) is called from the reference of this type of object.
In fact, in order to confirm the inheritance chain of the methods described here, you do not even need to run the code in the field. Place the code in Visual Studio and use rename in the refactor menu to modify the method name. After this, you will find that the method inheritance chain is interrupted, the Automatic Modification of the symbol name is also aborted.
Supplement
The preceding rules also apply to the this keyword. You only need to translate this into the corresponding type reference according to the current Code context, and then you can determine the final called code according to the described method. For example, in the foo1 method in C, assume that there is such a statement: "This. foo2 ()". When "D. foo2 (), it will be parsed to "C. foo1 () ", then, C. the foo1 () method is parsing the "This. when foo2 () "is parsed to D. foo2 ().
For the base keyword, it is relatively simple, just in the method of the base class (here, the word "method of the base class", please refer to the 6th pieces of "word conventions .) Find the method with the same name, and then call it. There is no process to parse the virtual function.
The method pointer encapsulated by the delegate object will still be resolved to the correct method according to the above rules when the delegate is called.