C # base and this
-- From Rocky Ren
2. Basic Concepts
Base and this are attributed to access keywords in C #. As the name suggests, they are used to implement access operations of the Inheritance Mechanism to satisfy access to object members, this provides a more flexible processing method for the polymorphism mechanism.
2.1 base keywords
It is used to implement access to the public or protected members of the base class in the derived class, but is limited to constructors, instance methods, and instance attribute accessors, the specific features summarized in msdn include:
• Call methods that have been overwritten by other methods on the base class.
• Specify the base class constructor to call when creating a derived class instance.
2.2 this keyword
It is used to reference the current instance of the class, and also includes inherited methods. This can usually be hidden. The summary function in msdn mainly includes:
• Restrict hidden members with similar names
• Passing objects as parameters to other methods
• Declare the Indexer
3. easy to understand
3.1.
Below is a small example to illustrate the application of base and this in access operations, so as to have a brief understanding of it. For more detailed rules and further details, we will go on to elaborate. This example does not have a complete design concept. It is mainly used to describe the key points and difficulties of using the base and this keywords. The details are as follows:
Using system;
Namespace anytao.net. my_must_net
{
Public class action
{
Public static void Torun (vehicle Vehicle)
{
Console. writeline ("{0} is running.", vehicle. tostring ());
}
}
Public class Vehicle
{
Private string name;
Private int speed;
Private string [] array = new string [10];
Public Vehicle ()
{
}
// Restrict hidden members by similar names
Public Vehicle (string name, int speed)
{
This. Name = Name;
This. speed = speed;
}
Public Virtual void showresult ()
{
Console. writeline ("the top speed of {0} is {1}.", name, speed );
}
Public void run ()
{
// Pass the parameters of the current instance
Action. Torun (this );
}
// Declare the indexer, which must be this, so that the object can be indexed like an array
Public String This [int Param]
{
Get {return array [Param];}
Set {array [Param] = value ;}
}
}
Public class car: Vehicle
{
// The derived class communicates with the base class. The base class is called first.
// Specify the base class constructor to call when creating a derived class instance
Public Car ()
: Base ("car", 200)
{}
Public Car (string name, int speed)
: This ()
{}
Public override void showresult ()
{
// Call a method that has been overwritten by other methods on the base class
Base. showresult ();
Console. writeline ("it's a car's result .");
}
}
Public class Audi: Car
{
Public Audi ()
: Base ("Audi", 300)
{}
Public Audi (string name, int speed)
: This ()
{
}
Public override void showresult ()
{
// It can be seen from layer-3 inheritance that base can only inherit its direct base class members
Base. showresult ();
Base. Run ();
Console. writeline ("It's Audi's result .");
}
}
Public class basethistester
{
Public static void main (string [] ARGs)
{
Audi = New Audi ();
Audi [1] = "A6 ";
Audi [2] = "A8 ";
Console. writeline (Audi [1]);
Audi. Run ();
Audi. showresult ();
}
}
}
3.2 Example
The above example shows all the basic functions used by base and this. The specific descriptions can be explained in the annotations. The following descriptions further describe and supplement the annotations, to illustrate the main points of application:
• Base is often used to communicate with the base class when the object of the derived class is initialized.
• Base can access the public and protected members of the base class. Private Members are not accessible.
• This refers to the class object itself, used to access all constants, fields, attributes, and method members of the class, regardless of the access element at any access level. Because this is only confined to the inside of the object and cannot be seen outside the object, this is the basic idea of this. In addition, static members are not part of objects, so they cannot be referenced in static methods.
• In multi-level inheritance, the base can point to the parent class methods in two cases: first, if there is an overload, the Base will point to the method of directly inherited parent class members, for example, in the showresult method of the Audi class, the base is used to access the car. showresult () method, but cannot access vehicle. the showresult () method. Instead, the base can point to the public or protected method of any parent class. For example, in the Audi class, you can use the base class to access the vehicle. run () method. Here we can use ildasm.exe to get the answer from the Il code.
. Method public hidebysig virtual instance void
Showresult () cel managed
{
// Code size 27 (0x1b)
. Maxstack 8
Il_0000: NOP
Il_0001: ldarg.0
// Base calls the parent class member
Il_0002: Call instance void anytao.net. my_must_net.car: showresult ()
Il_0007: NOP
Il_0008: ldarg.0
// Base calls the parent class member. Because car. Run () is not implemented, it points to a more advanced parent class.
Il_0009: Call instance void anytao.net. my_must_net.vehicle: Run ()
Il_000e: NOP
Il_000f: ldstr "It's Audi's result ."
Il_0014: Call void [mscorlib] system. Console: writeline (string)
Il_0019: NOP
Il_001a: Ret
} // End of method Audi: showresult
3.3 in-depth analysis
If there are three or more inheritance, what is the base of the lower-level derived class pointing? For example, in the. NET system, if the base is used for access, should it be a direct parent class instance or a top-level class instance?
First, we need to know the instantiation sequence during the class creation process to further understand the detailed execution process of the base mechanism. In general, the instantiation process first needs to instantiate its base class, and so on until the system. object is instantiated. Therefore, class instantiation always starts when system. Object. Object () is called. Therefore, the instantiation process of the class Audi in the example can be summarized as follows. For details, refer to the sample code analysis.
• Execute system. Object. Object ();
• Run vehicle. Vehicle (string name, int speed );
• Run car. Car ();
• Run car. Car (string name, int speed );
• Execute audi. Audi ();
• Run audi. Audi (string name, int speed ).
On the basis of fully understanding the instantiation sequence, we can smoothly grasp the implementation of base and this when acting on the constructor, and further understand the basic function details.
The more important analysis below is to analyze the Il decompilation code based on the ildasm.exe tool, so that we can have a deeper understanding of the application essence behind the base and this. Only in this way can we have a basic analysis of the technology.
The execution of the main method is as follows:
. Method public hidebysig static void main (string [] ARGs) cel managed
{
. Entrypoint
// Code size 61 (0x3d)
. Maxstack 3
. Locals Init (class anytao.net. my_must_net.audi V_0)
Il_0000: NOP
// Use the newobj command to create a new object and call the constructor for initialization.
Il_0001: newobj instance void anytao.net. my_must_net.audi:. ctor ()
Il_0006: stloc.0
Il_0007: ldloc.0
Il_0008: LDC. i4.1
Il_0009: ldstr "A6"
Il_000e: callvirt instance void anytao.net. my_must_net.vehicle: set_item (int32,
String)
Il_0013: NOP
Il_0014: ldloc.0
Il_0015: LDC. i4.2
Il_0016: ldstr "A8"
Il_001b: callvirt instance void anytao.net. my_must_net.vehicle: set_item (int32,
String)
Il_0020: NOP
Il_0021: ldloc.0
Il_0022: LDC. i4.1
Il_0023: callvirt instance string anytao.net. my_must_net.vehicle: get_item (int32)
Il_0028: Call void [mscorlib] system. Console: writeline (string)
Il_002d: NOP
Il_002e: ldloc.0
Il_002f: callvirt instance void anytao.net. my_must_net.vehicle: Run ()
Il_0034: NOP
Il_0035: ldloc.0
// Base. showresult finally calls the vehicle method of the highest level parent class,
// Instead of the direct parent class car. showresult () method, this should be followed
Il_0036: callvirt instance void anytao.net. my_must_net.vehicle: showresult ()
Il_003b: NOP
Il_003c: Ret
} // End of method basethistester: Main
Therefore, override the parent class method directs to the method Member of the highest level parent class.
4. General rules
• Use less or use less base and this. In addition to determining subclass name conflicts and calling other constructors in a constructor, the use of base and this may cause unnecessary results.
• Using base and this in static members is not allowed. The reason is that base and this access are class instances, that is, objects, while static members can only be accessed by classes and cannot be accessed by objects.
• Base is designed to achieve polymorphism.
• Only One constructor can be specified using the this or base keyword, that is, this and base cannot be applied to one constructor at the same time.
• In simple terms, base is used to access the rewritten base class members in the derived class, while this is used to access the members of this class, including the inherited public and protected members.
• In addition to base, the other way to access base class members is to convert the display type. This method cannot be a static method.