定义
接口 (interface) 定义了一个可由类和结构实现的协定。接口可以包含方法、属性、事件和索引器。接口不提供它所定义的成员的实现 — 它仅指定实现该接口的类或结构必须提供的成员。接口可支持多重继承。
接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数和返回值。C#接口中不能包含任何静态成员。
一个接口定义一个协定。实现某接口的类或结构必须遵守该接口定义的协定。一个接口可以从多个基接口继承,而一个类或结构可以实现多个接口。
接口可以包含方法、属性、事件和索引器。接口本身不提供它所定义的成员的实现。接口只指定实现该接口的类或结构必须提供的成员。
public delegate void StringListEvent(IStringList sender);
public interface IStringList
{
void Add(string s);//方法
int Count { get; }//属性
event StringListEvent Changed;//事件
string this[int index] { get; set; }//索引器
}
接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型,也不能包含任何种类的静态成员。
所有接口成员都隐式地具有 public 访问属性。接口成员声明中包含任何修饰符都属于编译时错误。
关于继承
当两个或更多个不相关(互不继承)的基接口中声明了具有相同名称或签名的成员时,就会发生多义性。在所有情况下,都可以使用显式强制转换来解决这种多义性。
多重继承接口中的直观隐藏规则是:如果成员在任一访问路径中被隐藏,那么它在所有访问路径中都被隐藏。如果类或结构实现一个包含被隐藏成员的接口,那么一些成员必须通过显式接口成员实现来实现。
interface IBase
{
void F(int i);
}
interface ILeft : IBase
{
new void F(int i);
}
interface IRight : IBase
{
void G();
}
interface IDerived : ILeft, IRight { }
class A
{
void Test(IDerived d)
{
d.F(1); // Invokes ILeft.F
((IBase)d).F(1); // Invokes IBase.F
((ILeft)d).F(1); // Invokes ILeft.F
((IRight)d).F(1); // Invokes IBase.F
}
}
显式实现
在方法调用、属性访问或索引器访问中,不能直接访问“显式接口成员实现”的成员,即使用它的完全限定名也不行。“显式接口成员实现”的成员只能通过接口实例来访问,并且在通过接口实例访问时,只能用该接口成员的名称来引用。
显式接口成员实现有两个主要用途:
由于显式接口成员实现不能通过类或结构实例来访问,因此它们就不属于类或结构的自身的公共接口。当需在一个公用的类或结构中实现一些仅供内部使用(不允许外界访问)的接口时,这就特别有用。
显式接口成员实现可以消除因同时含有多个相同签名的接口成员所引起的多义性。如果没有显式接口成员实现,一个类或结构就不可能为具有相同签名和返回类型的接口成员分别提供相应的实现,也不可能为具有相同签名和不同返回类型的所有接口成员中的任何一个提供实现。
接口映射
关于类或结构 C 的接口映射就是查找 C 的基类列表中指定的每个接口的每个成员的实现。对某个特定接口成员 I.M 的实现(其中 I 是声明了成员 M 的接口)的定位按下述规则执行:从 C 开始,按继承顺序,逐个检查它的每个后续基类(下面用 S 表示每个进行检查的类或结构),直到找到匹配项:
· 如果 S 包含一个与 I 和 M 匹配的显式接口成员实现的声明,那么此成员就是 I.M 的实现。
· 否则,如果 S 包含与 M 匹配的非静态的 public 成员声明,则此成员就是 I.M 的实现。如果找到多个匹配成员,则无法确定哪个成员是 I.M 的实现。只有 S 是构造类型(在此情况下,泛型类型中声明的两个成员具有不同的签名,但类型参数却使他们的签名相同)时,才会出现此情况。
如果不能为在 C 的基类列表中指定的所有接口的所有成员找到实现,则将发生编译时错误。请注意,接口的成员包括那些从基接口继承的成员。
根据接口映射的含义,类成员 A 在下列情况下与接口成员 B 匹配:
· A 和 B 都是方法,并且 A 和 B 的名称、类型和形参表都相同。
· A 和 B 都是属性,A 和 B 的名称和类型相同,并且 A 与 B 具有相同的访问器(如果 A 不是显式接口成员实现,则它可以具有其他访问器)。
· A 和 B 都是事件,并且 A 和 B 的名称和类型相同。
· A 和 B 都是索引器,A 和 B 的类型和形参表相同,并且 A 与 B 具有相同的访问器(如果 A 不是显式接口成员实现,则它可以具有其他访问器)。