Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / docs / ecma334 / 20.2.5.xml
1 <?xml version="1.0"?>
2 <clause number="20.2.5" title="Interface member access">
3   <paragraph>Interface members are accessed through member access (<hyperlink>14.5.4</hyperlink>) and indexer access (<hyperlink>14.5.6.2</hyperlink>) expressions of the form I.M and I[A], where I is an instance of an interface type, M is a method, property, or event of that interface type, and A is an indexer argument list. </paragraph>
4   <paragraph>For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup (<hyperlink>14.3</hyperlink>), method invocation (<hyperlink>14.5.5.1</hyperlink>), and indexer access (<hyperlink>14.5.6.2</hyperlink>) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This section shows several examples of such situations. In all cases, explicit casts can be used to resolve the ambiguities. </paragraph>
5   <paragraph>
6     <example>[Example: In the example <code_example><![CDATA[
7 interface IList  
8 {  
9    int Count { get; set; }  
10 }  
11 interface ICounter  
12 {  
13    void Count(int i);  
14 }  
15 interface IListCounter: IList, ICounter {}  
16 class C  
17 {  
18    void Test(IListCounter x) {  
19       x.Count(1);      // Error  
20       x.Count = 1;          // Error  
21       ((IList)x).Count = 1;   // Ok, invokes IList.Count.set  
22       ((ICounter)x).Count(1);  // Ok, invokes ICounter.Count  
23    }  
24 }  
25 ]]></code_example>the first two statements cause compile-time errors because the member lookup (<hyperlink>14.3</hyperlink>) of Count in IListCounter is ambiguous. As illustrated by the example, the ambiguity is resolved by casting x to the appropriate base interface type. Such casts have no run-time costs-they merely consist of viewing the instance as a less derived type at compile-time. end example]</example>
26   </paragraph>
27   <paragraph>
28     <example>[Example: In the example <code_example><![CDATA[
29 interface IInteger  
30 {  
31    void Add(int i);  
32 }  
33 interface IDouble  
34 {  
35    void Add(double d);  
36 }  
37 interface INumber: IInteger, IDouble {}  
38 class C  
39 {  
40    void Test(INumber n) {  
41       n.Add(1);      // Error, both Add methods are applicable  
42       n.Add(1.0);     // Ok, only IDouble.Add is applicable  
43       ((IInteger)n).Add(1);  // Ok, only IInteger.Add is a candidate  
44       ((IDouble)n).Add(1);   // Ok, only IDouble.Add is a candidate  
45    }  
46 }  
47 ]]></code_example>the invocation n.Add(1) is ambiguous because a method invocation (<hyperlink>14.5.5.1</hyperlink>) requires all overloaded candidate methods to be declared in the same type. However, the invocation n.Add(1.0) is permitted because only IDouble.Add is applicable. When explicit casts are inserted, there is only one candidate method, and thus no ambiguity. end example]</example>
48   </paragraph>
49   <paragraph>
50     <example>[Example: In the example <code_example><![CDATA[
51 interface IBase  
52 {  
53    void F(int i);  
54 }  
55 interface ILeft: IBase  
56 {  
57    new void F(int i);  
58 }  
59 interface IRight: IBase  
60 {  
61    void G();  
62 }  
63 interface IDerived: ILeft, IRight {}  
64 class A  
65 {  
66    void Test(IDerived d) {  
67       d.F(1);      // Invokes ILeft.F  
68       ((IBase)d).F(1);   // Invokes IBase.F  
69       ((ILeft)d).F(1);   // Invokes ILeft.F  
70       ((IRight)d).F(1);  // Invokes IBase.F  
71    }  
72 }  
73 ]]></code_example>the IBase.F member is hidden by the ILeft.F member. The invocation d.F(1) thus selects ILeft.F, even though IBase.F appears to not be hidden in the access path that leads through IRight. </example>
74   </paragraph>
75   <paragraph>
76     <example>The intuitive rule for hiding in multiple-inheritance interfaces is simply this: If a member is hidden in any access path, it is hidden in all access paths. Because the access path from IDerived to ILeft to IBase hides IBase.F, the member is also hidden in the access path from IDerived to IRight to IBase. end example]</example>
77   </paragraph>
78 </clause>