2010-06-21 Atsushi Enomoto <atsushi@ximian.com>
[mcs.git] / docs / ecma334 / 17.11.xml
blob21a9becc6d24b36fe5d0b4d4aac8e881da960d67
1 <?xml version="1.0"?>
2 <clause number="17.11" title="Static constructors">
3   <paragraph>A static constructor is a member that implements the actions required to initialize a class. Static constructors are declared using static-constructor-declarations: <grammar_production><name><non_terminal where="17.11">static-constructor-declaration</non_terminal></name> : <rhs><non_terminal where="24.2">attributes</non_terminal><opt/><non_terminal where="17.11">static-constructor-modifiers</non_terminal><non_terminal where="9.4.2">identifier</non_terminal><terminal>(</terminal><terminal>)</terminal><non_terminal where="17.11">static-constructor-body</non_terminal></rhs></grammar_production><grammar_production><name><non_terminal where="17.11">static-constructor-modifiers</non_terminal></name> : <rhs><keyword>extern</keyword><opt/><keyword>static</keyword></rhs><rhs><keyword>static</keyword><keyword>extern</keyword><opt/></rhs></grammar_production><grammar_production><name><non_terminal where="17.11">static-constructor-body</non_terminal></name> : <rhs><non_terminal where="15.2">block</non_terminal></rhs><rhs><terminal>;</terminal></rhs></grammar_production></paragraph>
4   <paragraph>A <non_terminal where="17.11">static-constructor-declaration</non_terminal> may include a set of attributes (<hyperlink>24</hyperlink>) and an extern modifier (<hyperlink>17.5.7</hyperlink>). </paragraph>
5   <paragraph>The identifier of a <non_terminal where="17.11">static-constructor-declaration</non_terminal> must name the class in which the static constructor is declared. If any other name is specified, a compile-time error occurs. </paragraph>
6   <paragraph>When a static constructor declaration includes an extern modifier, the static constructor is said to be an external static constructor. Because an external static constructor declaration provides no actual implementation, its <non_terminal where="17.11">static-constructor-body</non_terminal> consists of a semicolon. For all other static constructor declarations, the <non_terminal where="17.11">static-constructor-body</non_terminal> consists of a block, which specifies the statements to execute in order to initialize the class. This corresponds exactly to the <non_terminal where="17.5">method-body</non_terminal> of a static method with a <keyword>void</keyword> return type (<hyperlink>17.5.8</hyperlink>). </paragraph>
7   <paragraph>Static constructors are not inherited, and cannot be called directly. </paragraph>
8   <paragraph>The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain: <list><list_item> An instance of the class is created. </list_item><list_item> Any of the static members of the class are referenced. </list_item></list></paragraph>
9   <paragraph>If a class contains the Main method (<hyperlink>10.1</hyperlink>) in which execution begins, the static constructor for that class executes before the Main method is called. If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor. </paragraph>
10   <paragraph>
11     <example>[Example: The example <code_example><![CDATA[
12 using System;  
13 class Test  
14 {  
15    static void Main() {  
16       A.F();  
17       B.F();  
18    }  
19 }  
20 class A  
21 {  
22    static A() {  
23       Console.WriteLine("Init A");  
24    }  
25    public static void F() {  
26       Console.WriteLine("A.F");  
27    }  
28 }  
29 class B  
30 {  
31    static B() {  
32       Console.WriteLine("Init B");  
33    }  
34    public static void F() {  
35       Console.WriteLine("B.F");  
36    }  
37 }  
38 ]]></code_example>must produce the output: <code_example><![CDATA[
39 Init A  
40 A.F  
41 Init B  
42 B.F  
43 ]]></code_example>because the execution of A's static constructor is triggered by the call to A.F, and the execution of B's static constructor is triggered by the call to B.F. end example]</example>
44   </paragraph>
45   <paragraph>It is possible to construct circular dependencies that allow static fields with variable initializers to be observed in their default value state. </paragraph>
46   <paragraph>
47     <example>[Example: The example <code_example><![CDATA[
48 using System;  
49 class A  
50 {  
51    public static int X;  
52    static A() { X = B.Y + 1;}  
53 }  
54 class B  
55 {  
56    public static int Y = A.X + 1;  
57    static B() {}  
58    static void Main() {  
59       Console.WriteLine("X = {0}, Y = {1}", A.X, B.Y);  
60    }  
61 }  
62 ]]></code_example>produces the output <code_example><![CDATA[
63 X = 1, Y = 2  
64 ]]></code_example></example>
65   </paragraph>
66   <paragraph>
67     <example>To execute the Main method, the system first runs the initializer for B.Y, prior to class B's static constructor. </example>
68   </paragraph>
69   <paragraph>
70     <example>Y's initializer causes A's static constructor to be run because the value of A.X is referenced. The static constructor of A in turn proceeds to compute the value of X, and in doing so fetches the default value of Y, which is zero. A.X is thus initialized to 1. The process of running A's static field initializers and static constructor then completes, returning to the calculation of the initial value of Y, the result of which becomes 2. end example]</example>
71   </paragraph>
72 </clause>