When writing a program, it is inevitable to use static members. Because the access to static members is out of type objects, it is unreasonable to use non-static constructors, private methods, or some other methods .. NET provides the Member initialization statement and static constructor to initialize static members.
Based on the previous unit, we can know that the initialization statement of the static member will be executed earlier than the static constructor, and the advantages and limitations of the member initialization statement are also known. The difference between the static constructor and the instance constructor is mentioned here. Because the static constructor is called and executed by CLR, the static constructor can only be one, parameters are not allowed. The static constructor has no drawbacks over Member initialization.
In addition, the biggest problem with member Initialization is that exceptions cannot be captured. For common members, you can add try-catch when constructing type objects. For static members, sometimes it is difficult to determine which type of access statement will be executed first. If you add try-catch to each type of use, the program readability will be reduced. However, if this exception is thrown out, the entire program will crash. Then, the static constructor can better capture and handle exceptions.
The comparison between the static member initialization statement and the static constructor is roughly as follows.
|
Simplicity |
Security |
Exception Handling |
Static member Initialization |
Simplest |
Relatively secure |
Very difficult |
Static Constructor |
Relatively simple |
Safest |
Easy |
So what method is used to initialize static members? The following two suggestions are given:
The first is a simple static member, such as a value type, which is completed using the member initialization statement;
The initialization of the second static member is complex, or an exception may occur. You can use the static constructor to complete the initialization.
The content of this unit is basically finished. Now, the most important application "Singleton" for static members is to ensure the uniqueness of objects of this type. In fact, the implementation is very simple. Here is a simple example.
Public class mysingleton { Private Static readonly mysingleton _ theoneandonly; Static mysingleton () { _ Theoneandonly = new mysingleton (); } Public static mysingleton theonly { Get {return _ theoneandonly ;} }/// <Summary> /// Private constructor to avoid object created from outside /// </Summary> Private mysingleton () {} } |
When static members are initialized, you can analyze the object construction steps mentioned in the previous unit. It may seem abstract, especially when analyzing nested relationships. Here is an example.
Class { Public static int x = B .y; Static () { ++ X; } }Class B { Public static int y = a.x; Static B () { ++ Y; } } |
Let's guess what the output result of the following call is.
Debug. writeline (A. X. tostring ()); Debug. writeline (B. Y. tostring ()); |
The result is "2, 1", that is, the value of a.x is 2, and the value of B .y is 1.
To analyze such problems, you only need to remember three points.
The execution sequence of the first code. The code is executed first;
The second static member initialization statement must be executed before the static constructor;
The third static member initialization statement and static constructor are executed only once.
If you understand these three points, next we will analyze why the above results appear.
When the first statement is called,
Debug. writeline (A. X. tostring ()); |
First, access the type. initialize the static members of the type. Second, if there is a static constructor, you need to call it.
For a's static members, there is only "X". In accordance with the process of the previous unit, allocate space for them and perform initialization with 0, second, call the corresponding member initialization statement to initialize the static member.
The initialization statement of its members is "x = B .y", so you need to access "B .y" to initialize the static member "X.
For "B .y" access, access B is the same as access a. First, initialize the static members of this type, and then call it if there is a static constructor. While the static member of B only has "Y", allocate space for it, and perform initialization with 0. Second, call its corresponding member initialization statement to initialize this static member.
For the initialization statement of the "Y = a.x" Member, because it is not the first access type A, static member initialization and static constructor calls are not performed, direct access to "a.x. At this time, the value of "a.x" is 0, and the value of Y is 0. Then, the static constructor of B is executed, so that the value of Y is 1 after processing.
Then, the initialization statement "x = B .y" for the Members in a is executed. At this time, the values of X in the type are the same as those of Y in the B type, and the value is 1. However, both the static member initialization statement and the static constructor in B have been executed, but the static constructor IN A has not yet been executed. Therefore, after a's static constructor processing, the X value of A is 2, which is the final result.
The analysis process seems very difficult. In fact, as long as we grasp the three principles mentioned above, we can also analyze complicated problems.
-----------------------------------------------
Original article link: http://soft.yesky.com/188/2561688.shtml