Class instantiation of C #: open a pen question

Source: Internet
Author: User

I was impressed by a multiple-choice question, as shown in the following figure:

The sequence in which an X-type object is instantiated:

A. Call the X-Type constructor, call the constructor of the X-type base class, and call the constructor of the X-type internal fields.

B. Call the constructor of the X-type internal fields, call the constructor of the X-type base class, and call the X-Type constructor.

C. Call the constructor of the X-type base class, call the constructor of the X-Type constructor, and call the constructor of the X-type internal fields.

D. Call the constructor of the X-type base class, call the constructor of the X-type internal fields, and call the X-Type constructor.
 

I think this question is very poor. In the C ++ world, I will not hesitate to select D. However, since the field initializer is introduced in C #, the answer is completely dependent on how the class is designed. Okay, let's talk about the steps C # takes in type instantiation today.

First, we all know that for class objects, we need to use the keyword new to allocate memory for the new instance before executing the constructor. New can allocate enough space for the object on the stack based on the object type, and set all fields of the object as the default value. That is to say, CLR sets all reference type fields of this object to null, and sets all underlying binary representations of value type fields to 0 (essentially, whether it is to initialize the value type or reference type field to the "Default Value", they actually set their underlying data bit to 0 ). This is the first step to instantiate any class object.

For the moment, let's take a look at the following code without considering that the object has a specified base class:

Class MyClass {static MyClass () {Console. WriteLine ("the static constructor is called. ");} Private static Component staticField = new Component (" the static field is instantiated. "); Private Component instanceField = new Component (" the instance Member field is instantiated. "); Public MyClass () {Console. WriteLine (" the object constructor is called. ") ;}/// This type is used as a member of the MyClass class // This type can output custom information on the console during instantiation, class Component {public Component (String info) {Console. writeLine (info) ;}} class Program {static void Main (string [] args) {MyClass instance = new MyClass ();}}
Obviously, the constructors of static constructors and static fields are called first. This is because the CLR will first load this type before using any type of instance, so you need to call the static constructor and initialize the static members. But do we initialize static members first or call static constructor? The answer is to initialize static members, because CLR must ensure that all relevant member variables can be safely used when executing the constructor's method body. The same principle applies to the instance constructor and field, that is, the object member instantiation will be executed before the member constructor. By the way, the class definition function of directly initializing class object fields is completed by the class \ object field initializer. The following is the console output when the MyClass object is instantiated:

Static fields are instantiated. The static constructor is called. The instance Member field is instantiated. The object constructor is called.
Next, let's take a look at the situation where the object has a specified base class:

Class Base {static Base () {Console. WriteLine ("Base class static constructor is called. ");} Private static Component baseStaticField = new Component (" the base class static field is instantiated. "); Private Component baseInstanceField = new Component (" the base class instance Member field is instantiated. "); Public Base () {Console. WriteLine (" the Base class constructor is called. ") ;}// This type is used as a derived class. Like the base class, it also contains a static constructor, a static field, and an instance Member field. Class Derived: Base {static Derived () {Console. WriteLine ("the Derived class static constructor is called. ");} Private static Component derivedStaticField = new Component (" the static field of the derived class is instantiated. "); Private Component derivedInstanceField = new Component (" the member field of the derived class instance is instantiated. "); Public Derived () {Console. WriteLine (" the Derived class constructor is called. ") ;}/// This type is used as a member of the Base class and Derived class. // This type can output custom information on the console during instantiation, class Component {public Component (String info) {Console. writeLine (info) ;}}// instantiate a subclass object class Program {static void Main (string [] args) in the Main Program) {Derived derivedObject = new Derived ();}}

Similar to the MyClass in the previous example, the sub-class Derived and Base of the Base class both have static constructor and also contain one static member and one instance Member. When instantiating an instance of a subclass Derived object, the output results may not be easy to think:

The static field of the derived class is instantiated. The static constructor of the derived class is called. The instance Member field of the derived class is instantiated. The Base Static Field is instantiated. The base class static constructor is called. The base class instance Member field is instantiated. The base class constructor is called. The derived class constructor is called.
From the results, we can see that the static field initialization and static constructor call of the derived class will be executed before any initialization action of the base class. It is easy to understand that the static part of the Derived class is constructed first, because the Base class is not used before the CLR loads the Derived part of the Derived class, so it is not loaded first.

However, why is the instance Member field of the derived class initialized before the base class is constructed? The answer is related to the virtual function. Suppose there is such a base class that calls a virtual method in the constructor. Then there is another derived class that overwrites the virtual method of the base class and accesses its own instance Member field in this virtual method. All of this is completely legal (at least in the C # World), right? During the instantiation of a derived class object, the constructors of the base class will be called, then the virtual method will be called, and then the instance Member fields of the derived class will be accessed. So at this moment, the instance Member fields of this class must be ready! Therefore, the instance Member field of the derived class must be constructed before the base class.

Now, let's go back to our example. The rest is easy to understand: the base class is generated as expected, and the constructor of the derived class is called. So far, the object of a derived class is instantiated.

By the way, for Class field initiators or object field initiators, the order in which they initialize member fields is the sequence in which the Members appear in the class definition. By the way, if the program logic depends on the sequence of the members in the class definition, it is not easy to design, which may greatly reduce the ease of coding.

Now, when we look back at the beginning of the article, everything is clear-there is no correct answer! If the X type has an object field initializer and no instance fields are initialized in the constructor, B is the answer. If the X type does not have an object field initializer and the instance field is initialized in its constructor, select C as the answer. If the X type does not have an object field initializer and its constructor does not initialize any instance fields, select D as the answer. In other cases, there is no answer.


 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.