disable broken tests on net_4_0
[mcs.git] / docs / ecma334 / 24.4.2.xml
blob1a3004aa4973e9eeb3b925fe23c89374cb866ac6
1 <?xml version="1.0"?>
2 <clause number="24.4.2" title="The Conditional attribute">
3   <paragraph>The attribute Conditional enables the definition of conditional methods. The Conditional attribute indicates a condition by testing a conditional compilation symbol. Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. If the symbol is defined, the call is included; otherwise, the call is omitted. </paragraph>
4   <paragraph>A conditional method is subject to the following restrictions: <list><list_item> The conditional method must be a method in a <non_terminal where="17.1">class-declaration</non_terminal>. A compile-time error occurs if the Conditional attribute is specified on an interface method. </list_item><list_item> The conditional method must have a return type of <keyword>void</keyword>. </list_item><list_item> The conditional method must not be marked with the override modifier. A conditional method may be marked with the virtual modifier, however. Overrides of such a method are implicitly conditional, and must not be explicitly marked with a Conditional attribute. </list_item><list_item> The conditional method must not be an implementation of an interface method. Otherwise, a  compile-time error occurs. </list_item></list></paragraph>
5   <paragraph>In addition, a compile-time error occurs if a conditional method is used in a <non_terminal where="14.5.10.3">delegate-creation-expression</non_terminal>. </paragraph>
6   <paragraph>
7     <example>[Example: The example <code_example><![CDATA[
8 #define DEBUG  
9 using System;  
10 using System.Diagnostics;  
11 class Class1   
12 {  
13    [Conditional("DEBUG")]  
14    public static void M() {  
15       Console.WriteLine("Executed Class1.M");  
16    }  
17 }  
18 class Class2  
19 {  
20    public static void Test() {  
21       Class1.M();  
22    }  
23 }  
24 ]]></code_example>declares Class1.M as a conditional method. Class2's Test method calls this method. Since the conditional compilation symbol DEBUG is defined, if Class2.Test is called, it will call M. If the symbol DEBUG had not been defined, then Class2.Test would not call Class1.M. end example]</example>
25   </paragraph>
26   <paragraph>It is important to note that the inclusion or exclusion of a call to a conditional method is controlled by the conditional compilation symbols at the point of the call. <example>[Example: In the example <code_example><![CDATA[
27 // Begin class1.cs  
28 using System;  
29 using System.Diagnostics;  
30 class Class1   
31 {  
32    [Conditional("DEBUG")]  
33    public static void F() {  
34       Console.WriteLine("Executed Class1.F");  
35    }  
36 }  
37 // End class1.cs  
39 // Begin class2.cs  
40 #define DEBUG  
41 class Class2  
42 {  
43    public static void G() {  
44       Class1.F();    // F is called  
45    }  
46 }  
47 // End class2.cs  
49 // Begin class3.cs  
50 #undef DEBUG  
51 class Class3  
52 {  
53    public static void H() {  
54       Class1.F();    // F is not called  
55    }  
56 }  
57 // End class3.cs  
58 ]]></code_example>the classes Class2 and Class3 each contain calls to the conditional method Class1.F, which is conditional based on whether or not DEBUG is defined. Since this symbol is defined in the context of Class2 but not Class3, the call to F in Class2 is included, while the call to F in Class3 is omitted. end example]</example> </paragraph>
59   <paragraph>The use of conditional methods in an inheritance chain can be confusing. Calls made to a conditional method through base, of the form base.M, are subject to the normal conditional method call rules. </paragraph>
60   <paragraph>
61     <example>[Example: In the example <code_example><![CDATA[
62 // Begin class1.cs  
63 using System;  
64 using System.Diagnostics;  
65 class Class1   
66 {  
67    [Conditional("DEBUG")]  
68    public virtual void M() {  
69       Console.WriteLine("Class1.M executed");  
70    }  
71 }  
72 // End class1.cs  
74 // Begin class2.cs  
75 using System;  
76 class Class2: Class1  
77 {  
78    public override void M() {  
79       Console.WriteLine("Class2.M executed");  
80       base.M();       // base.M is not called!  
81    }  
82 }  
83 // End class2.cs  
85 // Begin class3.cs  
86 #define DEBUG  
87 using System;  
88 class Class3  
89 {  
90    public static void Test() {  
91       Class2 c = new Class2();  
92       c.M();              // M is called  
93    }  
94 }  
95 // End class3.cs  
96 ]]></code_example></example>
97   </paragraph>
98   <paragraph>
99     <example>Class2 includes a call to the M defined in its base class. This call is omitted because the base method is conditional based on the presence of the symbol DEBUG, which is undefined. Thus, the method writes to the console &quot;Class2.M executed&quot; only. Judicious use of <non_terminal where="9.5.3">pp-declaration</non_terminal>s can eliminate such problems. end example]</example>
100   </paragraph>
101 </clause>