int Count { get; }
event StringListEvent Changed;
string this[int index] { get; set; }
}
声明了一个接口,该接口的成员涵盖了所有可能作为接口成员的种类:方法、属性、事件和索引器。
interface-declaration 创建新的声明空间(第 错误!未找到引用源。 节),并且 interface-declaration 直接包含的 interface-member-declarations 将新成员提供给该声明空间。以下规则适用于 interface-member-declaration:
· 方法的名称必须与同一接口中声明的所有属性和事件的名称不同。此外,方法的签名(第 错误!未找到引用源。 节)必须不同于在同一接口中声明的所有其他方法的签名,并且在同一接口中声明的两种方法的签名不能只有 ref 和 out 不同。
· 属性或事件的名称必须与同一接口中声明的所有其他成员的名称不同。
· 一个索引器的签名必须区别于在同一接口中声明的其他所有索引器的签名。
准确地说,接口所继承的成员不是该接口的声明空间的一部分。因此,允许接口用与它所继承的成员相同的名称或签名来声明新的成员。发生这种情况时,则称派生的接口成员隐藏了基接口成员。隐藏一个继承的成员不算是错误,但这确实会导致编译器发出警告。为了避免出现上述警告,派生接口成员的声明中必须包含一个 new 修饰符,以指示该派生成员将要隐藏对应的基成员。第 错误!未找到引用源。 节中对该主题进行了进一步讨论。
如果在不隐藏所继承成员的声明中包含 new 修饰符,将对此状况发出警告。通过移除 new 修饰符可取消显示此警告。
请注意,严格来讲,类 object 中的成员不是任何接口的成员(第 1.2 节)。但是,通过在任何接口类型中进行成员查找,可获得类 object 中的成员(第 错误!未找到引用源。 节)。
1.1.1 接口方法
接口方法是使用 interface-method-declaration 来声明的:
interface-method-declaration:
attributesopt newopt return-type identifier ( formal-parameter-listopt ) ;
接口方法声明中的 attributes、return-type、identifier 和 formal-parameter-list 与类中的方法声明的对应项(第 错误!未找到引用源。 节)具有相同的意义。不允许接口方法声明指定方法体,因此,声明总是以分号结尾。
1.1.2 接口属性
接口属性是使用 interface-property-declaration 来声明的:
interface-property-declaration:
attributesopt newopt type identifier { interface-accessors }
interface-accessors:
attributesopt get ;
attributesopt set ;
attributesopt get ; attributesopt set ;
attributesopt set ; attributesopt get ;
接口属性声明中的 attributes、type 和 identifier 与类中的属性声明的对应项(第 错误!未找到引用源。 节)具有相同的意义。
接口属性声明的访问器与类属性声明(第 错误!未找到引用源。 节)的访问器相对应,不同之处在于接口属性声明的访问器体必须始终是一个分号。因此,访问器在这里只用于表示该属性为读写、只读还是只写。
1.1.3 接口事件
接口事件是使用 interface-event-declarations 来声明的:
interface-event-declaration:
attributesopt newopt event type identifier ;
接口事件声明中的 attributes、type 和 identifier 与类中事件声明的对应项(第 错误!未找到引用源。 节)具有相同的意义。
1.1.4 接口索引器
接口索引器是使用 interface-indexer-declaration 来声明的:
interface-indexer-declaration:
attributesopt newopt type this [ formal-parameter-list ] { interface-accessors }
接口索引器声明中的 attributes、type 和 formal-parameter-list 与类中索引器声明的对应项(第 错误!未找到引用源。 节)具有相同的意义。
接口索引器声明的访问器与类索引器声明(第 错误!未找到引用源。 节)的访问器相对应,不同之处在于接口索引器声明的访问器体必须始终是一个分号。因此,访问器在这里只用于表示该索引器为读写、只读还是只写。
1.1.5 接口成员访问
接口成员是通过 I.M 形式的成员访问(第 错误!未找到引用源。 节)表达式和 I[A] 形式的索引器访问(第 7.5.6.2 节)表达式来访问的,其中 I 是接口类型,M 是该接口类型的方法、属性或事件,A 是索引器参数列表。
对于严格单一继承(继承链中的每个接口均恰巧有零个或一个直接基接口)的接口,成员查找(第
错误!未找到引用源。 节)、方法调用(第 7.5.5.1 节)和索引器访问(第 7.5.6.2 节)规则的效果与类和结构的完全相同:派生程度较大的成员隐藏具有相同名称或签名的派生程度较小的成员。然而,对于多重继承接口,当两个或更多个不相关(互不继承)的基接口中声明了具有相同名称或签名的成员时,就会发生多义性。本节列出了此类情况的几个示例。在所有情况下,都可以使用显式强制转换来解决这种多义性。
在下面的示例中
interface IList
{
int Count { get; set; }
}
interface ICounter
{
void Count(int i);
}
interface IListCounter: IList, ICounter {}
class C
{
void Test(IListCounter x) {
x.Count(1); // Error
x.Count = 1; // Error
((IList)x).Count = 1; // Ok, invokes IList.Count.set
((ICounter)x).Count(1); // Ok, invokes ICounter.Count
}
}
由于在 IListCounter 中对 Count 的成员查找(第 错误!未找到引用源。 节)所获得的结果是不明确的,因此前两个语句将导致编译时错误。如示例所阐释的,将 x 强制转换为适当的基接口类型就可以消除这种多义性。此类强制转换没有运行时开销,它们只是在编译时将该实例视为派生程度较小的类型而已。
在下面的示例中
interface IInteger
{
void Add(int i);
}
interface IDouble
{
void Add(double d);
}
interface INumber: IInteger, IDouble {}
class C
{
void Test(INumber n) {
n.Add(1); // Invokes IInteger.Add
n.Add(1.0); // Only IDouble.Add is applicable
((IInteger)n).Add(1); // Only IInteger.Add is a candidate
((IDouble)n).Add(1); // Only IDouble.Add is a candidate
}
}
评论