Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / docs / ecma334 / 17.9.3.xml
1 <?xml version="1.0"?>
2 <clause number="17.9.3" title="Conversion operators">
3   <paragraph>A conversion operator declaration introduces a user-defined conversion (<hyperlink>13.4</hyperlink>), which augments the  pre-defined implicit and explicit conversions. </paragraph>
4   <paragraph>A conversion operator declaration that includes the implicit keyword introduces a user-defined implicit conversion. Implicit conversions can occur in a variety of situations, including function member invocations, cast expressions, and assignments. This is described further in <hyperlink>13.1</hyperlink>. </paragraph>
5   <paragraph>A conversion operator declaration that includes the explicit keyword introduces a user-defined explicit conversion. Explicit conversions can occur in cast expressions, and are described further in <hyperlink>13.2</hyperlink>. </paragraph>
6   <paragraph>A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from a source type S to a target type T provided all of the following are true: <list><list_item> S and T are different types. </list_item><list_item> Either S or T is the class or struct type in which the operator declaration takes place. </list_item><list_item> Neither S nor T is object or an <non_terminal where="11.2">interface-type</non_terminal>. </list_item><list_item> T is not a base class of S, and S is not a base class of T. </list_item></list></paragraph>
7   <paragraph>From the second rule it follows that a conversion operator must convert either to or from the class or struct type in which the operator is declared. <example>[Example: For example, it is possible for a class or struct type C to define a conversion from C to <keyword>int</keyword> and from <keyword>int</keyword> to C, but not from <keyword>int</keyword> to <keyword>bool</keyword>. end example]</example> </paragraph>
8   <paragraph>It is not possible to redefine a pre-defined conversion. Thus, conversion operators are not allowed to convert from or to object because implicit and explicit conversions already exist between object and all other types. Likewise, neither the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist. </paragraph>
9   <paragraph>User-defined conversions are not allowed to convert from or to <non_terminal where="11.2">interface-type</non_terminal>s. In particular, this restriction ensures that no user-defined transformations occur when converting to an <non_terminal where="11.2">interface-type</non_terminal>, and that a conversion to an <non_terminal where="11.2">interface-type</non_terminal> succeeds only if the object being converted actually implements the specified <non_terminal where="11.2">interface-type</non_terminal>. </paragraph>
10   <paragraph>The signature of a conversion operator consists of the source type and the target type. (Note that this is the only form of member for which the return type participates in the signature.) The implicit or explicit classification of a conversion operator is not part of the operator's signature. Thus, a class or struct cannot declare both an implicit and an explicit conversion operator with the same source and target types. </paragraph>
11   <paragraph>
12     <note>[Note: In general, user-defined implicit conversions should be designed to never throw exceptions and never lose information. If a user-defined conversion can give rise to exceptions (for example, because the source argument is out of range) or loss of information (such as discarding high-order bits), then that conversion should be defined as an explicit conversion. end note]</note>
13   </paragraph>
14   <paragraph>
15     <example>[Example: In the example <code_example><![CDATA[
16 using System;  
17 public struct Digit  
18 {  
19    byte value;  
20    public Digit(byte value) {  
21       if (value < 0 || value > 9) throw new ArgumentException();  
22       this.value = value;  
23    }  
24    public static implicit operator byte(Digit d) {  
25       return d.value;  
26    }  
27    public static explicit operator Digit(byte b) {  
28       return new Digit(b);  
29    }  
30 }  
31 ]]></code_example>the conversion from Digit to <keyword>byte</keyword> is implicit because it never throws exceptions or loses information, but the conversion from <keyword>byte</keyword> to Digit is explicit since Digit can only represent a subset of the possible values of a <keyword>byte</keyword>. end example]</example>
32   </paragraph>
33 </clause>