接口Interfaces

接口定义协定。An interface defines a contract. 实现接口的类或结构必须遵循它的协定。A class or struct that implements an interface must adhere to its contract. 接口可以从多个基接口继承,类或结构可以实现多个接口。An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

接口可以包含方法、属性、事件和索引器。Interfaces can contain methods, properties, events, and indexers. 接口本身不提供它定义的成员的实现。The interface itself does not provide implementations for the members that it defines. 接口仅指定实现接口的类或结构必须提供的成员。The interface merely specifies the members that must be supplied by classes or structs that implement the interface.

接口声明Interface declarations

Interface_declaration 是声明新接口类型) 的 type_declaration (类型声明An interface_declaration is a type_declaration (Type declarations) that declares a new interface type.

interface_declaration
    : attributes? interface_modifier* 'partial'? 'interface'
      identifier variant_type_parameter_list? interface_base?
      type_parameter_constraints_clause* interface_body ';'?
    ;

Interface_declaration 包含一组可选的 特性 (特性) ,后跟一组可选的 interface_modifier s (接口修饰符) ,后跟一个可选 partial 修饰符,后跟关键字 interface 和命名该接口的 标识符,后跟一个可选的 variant_type_parameter_list 规范 (variant 类型参数列表) ,后跟一个可选的 interface_base 规范 (基接口) ,后跟一个可选的 type_parameter_constraints_clause () 类型参数约束,后跟一个可选的 interface_body接口体 (,后面可以跟一个分号。An interface_declaration consists of an optional set of attributes (Attributes), followed by an optional set of interface_modifier s (Interface modifiers), followed by an optional partial modifier, followed by the keyword interface and an identifier that names the interface, followed by an optional variant_type_parameter_list specification (Variant type parameter lists), followed by an optional interface_base specification (Base interfaces), followed by an optional type_parameter_constraints_clause s specification (Type parameter constraints), followed by an interface_body (Interface body), optionally followed by a semicolon.

接口修饰符Interface modifiers

Interface_declaration 可以选择性地包含一系列接口修饰符:An interface_declaration may optionally include a sequence of interface modifiers:

interface_modifier
    : 'new'
    | 'public'
    | 'protected'
    | 'internal'
    | 'private'
    | interface_modifier_unsafe
    ;

同一修饰符在接口声明中出现多次是编译时错误。It is a compile-time error for the same modifier to appear multiple times in an interface declaration.

new仅允许在类中定义的接口上使用修饰符。The new modifier is only permitted on interfaces defined within a class. 它指定接口按 新修饰符中所述隐藏同名的继承成员。It specifies that the interface hides an inherited member by the same name, as described in The new modifier.

public、、 protected internalprivate 修饰符控制接口的可访问性。The public, protected, internal, and private modifiers control the accessibility of the interface. 根据接口声明发生的上下文,可以 (声明的可访问性) 中仅允许某些修饰符。Depending on the context in which the interface declaration occurs, only some of these modifiers may be permitted (Declared accessibility).

Partial 修饰符Partial modifier

partial修饰符指示此 interface_declaration 是分部类型声明。The partial modifier indicates that this interface_declaration is a partial type declaration. 在一个封闭命名空间或类型声明中具有相同名称的多个分部接口声明组合在一起,并遵循在 部分类型中指定的规则形成一个接口声明。Multiple partial interface declarations with the same name within an enclosing namespace or type declaration combine to form one interface declaration, following the rules specified in Partial types.

变体类型参数列表Variant type parameter lists

变体类型参数列表只能出现在接口类型和委托类型上。Variant type parameter lists can only occur on interface and delegate types. 与普通 type_parameter_list s 的不同是每个类型参数上的可选 variance_annotationThe difference from ordinary type_parameter_list s is the optional variance_annotation on each type parameter.

variant_type_parameter_list
    : '<' variant_type_parameters '>'
    ;

variant_type_parameters
    : attributes? variance_annotation? type_parameter
    | variant_type_parameters ',' attributes? variance_annotation? type_parameter
    ;

variance_annotation
    : 'in'
    | 'out'
    ;

如果方差批注为 out ,则将类型参数称为 *协变 _。If the variance annotation is out, the type parameter is said to be *covariant _. 如果方差批注为 in ,则将类型参数称为 *逆变*If the variance annotation is in, the type parameter is said to be contravariant. 如果没有方差批注,则将类型参数称为 _ 固定 *。If there is no variance annotation, the type parameter is said to be _*invariant**.

示例中In the example

interface C<out X, in Y, Z> 
{
  X M(Y y);
  Z P { get; set; }
}

X 是协变的, Y 是逆变的并且 Z 是固定的。X is covariant, Y is contravariant and Z is invariant.

差异安全Variance safety

类型的类型参数列表中的差异批注的出现次数限制了类型在类型声明内可能出现的位置。The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration.

T如果以下包含其中一项,则类型为 输出不安全A type T is output-unsafe if one of the following holds:

  • T 是逆变类型参数T is a contravariant type parameter
  • T 是一个带有输出不安全元素类型的数组类型T is an array type with an output-unsafe element type
  • T 是从泛型类型构造的接口或委托类型, S<A1,...,Ak> S<X1,...,Xk> 其中至少 Ai 包含以下项之一:T is an interface or delegate type S<A1,...,Ak> constructed from a generic type S<X1,...,Xk> where for at least one Ai one of the following holds:
    • Xi 是协变或固定,并且 Ai 是输出不安全的。Xi is covariant or invariant and Ai is output-unsafe.
    • Xi 为逆变或固定,并且 Ai 是输入安全的。Xi is contravariant or invariant and Ai is input-safe.

T如果包含以下内容之一,则类型为 输入-不安全A type T is input-unsafe if one of the following holds:

  • T 是协变类型参数T is a covariant type parameter
  • T 是具有输入不安全元素类型的数组类型T is an array type with an input-unsafe element type
  • T 是从泛型类型构造的接口或委托类型, S<A1,...,Ak> S<X1,...,Xk> 其中至少 Ai 包含以下项之一:T is an interface or delegate type S<A1,...,Ak> constructed from a generic type S<X1,...,Xk> where for at least one Ai one of the following holds:
    • Xi 是协变或固定的,并且 Ai 是输入不安全的。Xi is covariant or invariant and Ai is input-unsafe.
    • Xi 为逆变或固定,并且 Ai 是输出不安全的。Xi is contravariant or invariant and Ai is output-unsafe.

在直观的输出位置中禁止使用不安全的输出类型,在输入位置禁止输入不安全类型。Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position.

如果类型不是输出安全类型,则为 *输出安全 的; 如果不是输入安全的,则为 _ *输入安全**。A type is output-safe _ if it is not output-unsafe, and _ input-safe if it is not input-unsafe.

方差转换Variance conversion

变体批注的目的在于提供更多宽松 (但仍类型安全) 转换到接口和委托类型。The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. 为此,将隐式 (隐式转换 的定义) 和显式转换 (显式 转换,) 使用 convertibility 的概念,定义如下:To this end the definitions of implicit (Implicit conversions) and explicit conversions (Explicit conversions) make use of the notion of variance-convertibility, which is defined as follows:

如果类型 T<A1,...,An> T<B1,...,Bn> T 是使用变量类型参数声明的接口或委托类型 T<X1,...,Xn> ,并且对于每个 variant 类型参数,则类型对类型的变体可转换为 Xi 以下类型之一:A type T<A1,...,An> is variance-convertible to a type T<B1,...,Bn> if T is either an interface or a delegate type declared with the variant type parameters T<X1,...,Xn>, and for each variant type parameter Xi one of the following holds:

  • Xi是协变的,并且存在从到的隐式引用或标识转换 Ai``BiXi is covariant and an implicit reference or identity conversion exists from Ai to Bi
  • Xi为逆变,并且存在从到的隐式引用或标识转换 Bi``AiXi is contravariant and an implicit reference or identity conversion exists from Bi to Ai
  • Xi是固定的,存在从到的标识转换 Ai``BiXi is invariant and an identity conversion exists from Ai to Bi

基接口Base interfaces

接口可以从零个或多个接口类型继承,这些接口类型称为接口的 显式基接口An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. 如果接口具有一个或多个显式基接口,则在该接口的声明中,接口标识符后跟一个冒号和一个逗号分隔的基接口类型列表。When an interface has one or more explicit base interfaces, then in the declaration of that interface, the interface identifier is followed by a colon and a comma separated list of base interface types.

interface_base
    : ':' interface_type_list
    ;

对于构造接口类型,通过对泛型类型声明采用显式基接口声明,并为基接口声明中的每个 type_parameter 替换构造的类型的相应 type_argument ,可以形成显式基接口。For a constructed interface type, the explicit base interfaces are formed by taking the explicit base interface declarations on the generic type declaration, and substituting, for each type_parameter in the base interface declaration, the corresponding type_argument of the constructed type.

接口的显式基接口必须至少具有与接口本身相同的可访问 性 (辅助功能约束) 。The explicit base interfaces of an interface must be at least as accessible as the interface itself (Accessibility constraints). 例如, private internal 在接口的 interface_base 中指定或接口是编译时错误 publicFor example, it is a compile-time error to specify a private or internal interface in the interface_base of a public interface.

接口直接或间接从自身继承时,会发生编译时错误。It is a compile-time error for an interface to directly or indirectly inherit from itself.

接口的 基接口 是显式基接口及其基接口。The base interfaces of an interface are the explicit base interfaces and their base interfaces. 换言之,基接口集是显式基接口的完全可传递的闭包、其显式基接口等。In other words, the set of base interfaces is the complete transitive closure of the explicit base interfaces, their explicit base interfaces, and so on. 接口继承其基接口的所有成员。An interface inherits all members of its base interfaces. 示例中In the example

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

interface IListBox: IControl
{
    void SetItems(string[] items);
}

interface IComboBox: ITextBox, IListBox {}

的基接口 IComboBoxIControlITextBoxIListBoxthe base interfaces of IComboBox are IControl, ITextBox, and IListBox.

换言之, IComboBox 以上接口继承成员 SetTextSetItems PaintIn other words, the IComboBox interface above inherits members SetText and SetItems as well as Paint.

接口的每个基接口都必须是输出安全 (差异安全) 。Every base interface of an interface must be output-safe (Variance safety). 实现接口的类或结构还隐式实现了接口的所有基接口。A class or struct that implements an interface also implicitly implements all of the interface's base interfaces.

接口正文Interface body

接口的 interface_body 定义接口的成员。The interface_body of an interface defines the members of the interface.

interface_body
    : '{' interface_member_declaration* '}'
    ;

接口成员Interface members

接口的成员是继承自基接口的成员和接口本身声明的成员。The members of an interface are the members inherited from the base interfaces and the members declared by the interface itself.

interface_member_declaration
    : interface_method_declaration
    | interface_property_declaration
    | interface_event_declaration
    | interface_indexer_declaration
    ;

接口声明可以声明零个或多个成员。An interface declaration may declare zero or more members. 接口成员必须是方法、属性、事件或索引器。The members of an interface must be methods, properties, events, or indexers. 接口不能包含常量、字段、运算符、实例构造函数、析构函数或类型,也不能包含任何类型的静态成员。An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.

所有接口成员隐式具有公共访问权限。All interface members implicitly have public access. 接口成员声明包含任何修饰符是编译时错误。It is a compile-time error for interface member declarations to include any modifiers. 特别是,不能用修饰符 abstractpublicprotected 、、、、 internal private virtual overridestatic 声明接口成员。In particular, interfaces members cannot be declared with the modifiers abstract, public, protected, internal, private, virtual, override, or static.

示例The example

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; }
}

声明一个接口,该接口包含每个可能的成员类型:方法、属性、事件和索引器。declares an interface that contains one each of the possible kinds of members: A method, a property, an event, and an indexer.

Interface_declaration (声明) 创建新的声明空间,并且 interface_declaration 立即包含的 interface_member_declaration 会将新成员引入此声明空间。An interface_declaration creates a new declaration space (Declarations), and the interface_member_declaration s immediately contained by the interface_declaration introduce new members into this declaration space. 以下规则适用于 interface_member_declarationThe following rules apply to interface_member_declaration s:

  • 方法的名称必须不同于在同一接口中声明的所有属性和事件的名称。The name of a method must differ from the names of all properties and events declared in the same interface. 此外, (签名和方法的 重载) 的签名必须与在同一接口中声明的所有其他方法的签名不同,并且在同一接口中声明的两个方法的签名不只是与和不同 ref outIn addition, the signature (Signatures and overloading) of a method must differ from the signatures of all other methods declared in the same interface, and two methods declared in the same interface may not have signatures that differ solely by ref and out.
  • 属性或事件的名称必须不同于在同一接口中声明的所有其他成员的名称。The name of a property or event must differ from the names of all other members declared in the same interface.
  • 索引器的签名必须不同于同一接口中声明的所有其他索引器的签名。The signature of an indexer must differ from the signatures of all other indexers declared in the same interface.

接口的继承成员特别不是接口的声明空间的一部分。The inherited members of an interface are specifically not part of the declaration space of the interface. 因此,允许接口声明与继承成员具有相同名称或签名的成员。Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. 出现这种情况时,会说派生接口成员隐藏基接口成员。When this occurs, the derived interface member is said to hide the base interface member. 隐藏继承成员不被视为错误,但会导致编译器发出警告。Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. 若要禁止显示警告,派生接口成员的声明必须包含 new 修饰符以指示该派生成员用于隐藏基成员。To suppress the warning, the declaration of the derived interface member must include a new modifier to indicate that the derived member is intended to hide the base member. 本主题将在 通过继承隐藏中进一步进行讨论。This topic is discussed further in Hiding through inheritance.

如果 new 修饰符包含在不隐藏继承成员的声明中,则会发出警告。If a new modifier is included in a declaration that doesn't hide an inherited member, a warning is issued to that effect. 通过删除修饰符,可取消显示此警告 newThis warning is suppressed by removing the new modifier.

请注意,类中的成员 object 并不严格地说,任何接口 (接口成员) 的成员。Note that the members in class object are not, strictly speaking, members of any interface (Interface members). 但是,类中的成员 object 可通过成员查找在任何接口类型 (成员查找) 中使用。However, the members in class object are available via member lookup in any interface type (Member lookup).

接口方法Interface methods

接口方法是使用 interface_method_declaration s 声明的:Interface methods are declared using interface_method_declaration s:

interface_method_declaration
    : attributes? 'new'? return_type identifier type_parameter_list
      '(' formal_parameter_list? ')' type_parameter_constraints_clause* ';'
    ;

接口方法声明的 特性return_type标识符formal_parameter_list 与类 (方法) 中的方法声明具有相同的含义。The attributes, return_type, identifier, and formal_parameter_list of an interface method declaration have the same meaning as those of a method declaration in a class (Methods). 不允许接口方法声明指定方法体,因此声明始终以分号结束。An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon.

接口方法的每个形参类型都必须是输入安全的 (方差安全) ,返回类型必须是 void 或输出安全类型。Each formal parameter type of an interface method must be input-safe (Variance safety), and the return type must be either void or output-safe. 此外,对方法的任何类型参数的每个类类型约束、接口类型约束和类型形参约束都必须为输入安全类型。Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method must be input-safe.

这些规则可确保接口的任何协变或逆变使用保持类型安全。These rules ensure that any covariant or contravariant usage of the interface remains type-safe. 例如,For example,

interface I<out T> { void M<U>() where U : T; }

是非法的,因为 T 作为的类型参数约束的使用 U 不是输入安全的。is illegal because the usage of T as a type parameter constraint on U is not input-safe.

此限制没有发生,则可以通过以下方式违反类型安全:Were this restriction not in place it would be possible to violate type safety in the following manner:

class B {}
class D : B{}
class E : B {}
class C : I<D> { public void M<U>() {...} }
...
I<B> b = new C();
b.M<E>();

这实际上是对的调用 C.M<E>This is actually a call to C.M<E>. 但调用需要 E 从派生 D ,因此在此处违反类型安全。But that call requires that E derive from D, so type safety would be violated here.

接口属性Interface properties

接口属性是使用 interface_property_declaration s 声明的:Interface properties are declared using interface_property_declaration s:

interface_property_declaration
    : attributes? 'new'? type identifier '{' interface_accessors '}'
    ;

interface_accessors
    : attributes? 'get' ';'
    | attributes? 'set' ';'
    | attributes? 'get' ';' attributes? 'set' ';'
    | attributes? 'set' ';' attributes? 'get' ';'
    ;

接口属性声明的特性、类型和标识符与类中属性声明的 特性类型标识符) (属性 的含义相同。The attributes, type, and identifier of an interface property declaration have the same meaning as those of a property declaration in a class (Properties).

接口属性声明的访问器与类属性声明的访问器) (访问器 的访问器不同,只不过访问器体必须始终是一个分号。The accessors of an interface property declaration correspond to the accessors of a class property declaration (Accessors), except that the accessor body must always be a semicolon. 因此,访问器仅指示该属性是读写、只读还是只写。Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.

如果存在 get 访问器,则接口属性的类型必须为输出安全类型; 如果存在 set 访问器,则必须是输入安全类型。The type of an interface property must be output-safe if there is a get accessor, and must be input-safe if there is a set accessor.

接口事件Interface events

使用 interface_event_declaration s 声明接口事件:Interface events are declared using interface_event_declaration s:

interface_event_declaration
    : attributes? 'new'? 'event' type identifier ';'
    ;

接口事件声明的特性、类型和标识符与类中的事件声明的 特性类型标识符) (事件 的含义相同。The attributes, type, and identifier of an interface event declaration have the same meaning as those of an event declaration in a class (Events).

接口事件的类型必须是输入安全类型。The type of an interface event must be input-safe.

接口索引器Interface indexers

接口索引器使用 interface_indexer_declaration s 来声明:Interface indexers are declared using interface_indexer_declaration s:

interface_indexer_declaration
    : attributes? 'new'? type 'this' '[' formal_parameter_list ']' '{' interface_accessors '}'
    ;

接口索引器声明的 特性类型Formal_parameter_list 与类 (索引器) 类中的索引器声明具有相同的含义。The attributes, type, and formal_parameter_list of an interface indexer declaration have the same meaning as those of an indexer declaration in a class (Indexers).

接口索引器声明的访问器与类索引器声明的访问器) (索引 器的访问器不同,只不过访问器体必须始终是一个分号。The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration (Indexers), except that the accessor body must always be a semicolon. 因此,访问器仅指示索引器是读写、只读还是只写。Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.

接口索引器的所有形参类型都必须为输入安全类型。All the formal parameter types of an interface indexer must be input-safe . 此外,任何 outref 形参类型也必须是输出安全类型。In addition, any out or ref formal parameter types must also be output-safe. 请注意, out 由于基础执行平台的限制,甚至参数需要是输入安全的参数。Note that even out parameters are required to be input-safe, due to a limitation of the underlying execution platform.

如果存在 get 访问器,则接口索引器的类型必须是输出安全的,如果存在 set 访问器,则必须是输入安全的类型。The type of an interface indexer must be output-safe if there is a get accessor, and must be input-safe if there is a set accessor.

接口成员访问Interface member access

接口成员是 通过成员访问 (访问) 和索引器访问 (索引器访问索引器 访问) 表达式, I.M I[A] 其中 I 是接口类型, M 是接口类型的方法、属性或事件, A 是索引器参数列表。Interface members are accessed through member access (Member access) and indexer access (Indexer access) expressions of the form I.M and I[A], where I is an interface type, M is a method, property, or event of that interface type, and A is an indexer argument list.

对于严格为单一继承 (接口的接口,继承链中的每个接口都刚好有零个或一个直接基接口) 、成员查找 (成员查找) 、方法调用 (方法 调用) 和索引器访问 (索引器 access) 规则与类和结构的访问权限完全相同:更多的派生成员隐藏具有相同名称或签名的派生成员。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 (Member lookup), method invocation (Method invocations), and indexer access (Indexer access) 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.

示例中In the example

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
    }
}

前两个语句会导致编译时错误,因为中的成员查找 (成员查找) Count IListCounter 是不明确的。the first two statements cause compile-time errors because the member lookup (Member lookup) of Count in IListCounter is ambiguous. 如示例所示,通过将强制转换 x 为相应的基接口类型来解决歧义。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.

示例中In the example

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
    }
}

调用 n.Add(1) IInteger.Add 通过应用 重载决策的重载决策规则来选择。the invocation n.Add(1) selects IInteger.Add by applying the overload resolution rules of Overload resolution. 同样,调用也会 n.Add(1.0) 选择 IDouble.AddSimilarly the invocation n.Add(1.0) selects IDouble.Add. 插入显式强制转换后,只能有一个候选方法,因此没有任何多义性。When explicit casts are inserted, there is only one candidate method, and thus no ambiguity.

示例中In the example

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
    }
}

成员 IBase.FILeft.F 成员隐藏。the IBase.F member is hidden by the ILeft.F member. d.F(1)这样 ILeft.F ,调用会选择,即使 IBase.F 似乎不会隐藏在导致的访问路径中 IRightThe 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.

在多继承接口中隐藏的直观规则是:如果某个成员在任何访问路径中都隐藏,则它会在所有访问路径中隐藏。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. 由于从到的访问 IDerived 路径 ILeft IBase 隐藏 IBase.F ,成员在从到的访问路径中也将隐藏 IDerived IRight IBaseBecause 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.

完全限定的接口成员名称Fully qualified interface member names

接口成员有时通过其 完全限定名称 来引用。An interface member is sometimes referred to by its fully qualified name. 接口成员的完全限定名称由声明成员的接口的名称(后跟一个点,后跟成员的名称)组成。The fully qualified name of an interface member consists of the name of the interface in which the member is declared, followed by a dot, followed by the name of the member. 成员的完全限定名引用声明该成员的接口。The fully qualified name of a member references the interface in which the member is declared. 例如,给定声明For example, given the declarations

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

的完全限定名 PaintIControl.Paint ,的完全限定名 SetTextITextBox.SetTextthe fully qualified name of Paint is IControl.Paint and the fully qualified name of SetText is ITextBox.SetText.

在上面的示例中,不能将 Paint 作为引用 ITextBox.PaintIn the example above, it is not possible to refer to Paint as ITextBox.Paint.

如果接口是命名空间的一部分,则接口成员的完全限定名称包括命名空间名称。When an interface is part of a namespace, the fully qualified name of an interface member includes the namespace name. 例如For example

namespace System
{
    public interface ICloneable
    {
        object Clone();
    }
}

此处,方法的完全限定名 CloneSystem.ICloneable.CloneHere, the fully qualified name of the Clone method is System.ICloneable.Clone.

接口实现Interface implementations

接口可以由类和结构实现。Interfaces may be implemented by classes and structs. 为了指示类或结构直接实现接口,接口标识符包含在类或结构的基类列表中。To indicate that a class or struct directly implements an interface, the interface identifier is included in the base class list of the class or struct. 例如:For example:

interface ICloneable
{
    object Clone();
}

interface IComparable
{
    int CompareTo(object other);
}

class ListEntry: ICloneable, IComparable
{
    public object Clone() {...}
    public int CompareTo(object other) {...}
}

直接实现接口的类或结构还直接实现接口的所有基接口。A class or struct that directly implements an interface also directly implements all of the interface's base interfaces implicitly. 即使类或结构未在基类列表中显式列出所有基接口,也是如此。This is true even if the class or struct doesn't explicitly list all base interfaces in the base class list. 例如:For example:

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

class TextBox: ITextBox
{
    public void Paint() {...}
    public void SetText(string text) {...}
}

此处,类 TextBox 实现 IControlITextBoxHere, class TextBox implements both IControl and ITextBox.

当类 C 直接实现接口时,从 C 派生的所有类也将隐式实现接口。When a class C directly implements an interface, all classes derived from C also implement the interface implicitly. 类声明中指定的基接口可以是构造接口类型 (构造 类型) 。The base interfaces specified in a class declaration can be constructed interface types (Constructed types). 基接口本身不能是类型参数,但它可以涉及范围内的类型参数。A base interface cannot be a type parameter on its own, though it can involve the type parameters that are in scope. 下面的代码演示了类如何实现和扩展构造类型:The following code illustrates how a class can implement and extend constructed types:

class C<U,V> {}

interface I1<V> {}

class D: C<string,int>, I1<string> {}

class E<T>: C<int,T>, I1<T> {}

泛型类声明的基接口必须满足 实现接口唯一性中描述的唯一性规则。The base interfaces of a generic class declaration must satisfy the uniqueness rule described in Uniqueness of implemented interfaces.

显式接口成员实现Explicit interface member implementations

为了实现接口,类或结构可以声明 显式接口成员实现For purposes of implementing interfaces, a class or struct may declare explicit interface member implementations. 显式接口成员实现是指引用完全限定的接口成员名称的方法、属性、事件或索引器声明。An explicit interface member implementation is a method, property, event, or indexer declaration that references a fully qualified interface member name. 例如For example

interface IList<T>
{
    T[] GetElements();
}

interface IDictionary<K,V>
{
    V this[K key];
    void Add(K key, V value);
}

class List<T>: IList<T>, IDictionary<int,T>
{
    T[] IList<T>.GetElements() {...}
    T IDictionary<int,T>.this[int index] {...}
    void IDictionary<int,T>.Add(int index, T value) {...}
}

此处 IDictionary<int,T>.thisIDictionary<int,T>.Add 是显式接口成员实现。Here IDictionary<int,T>.this and IDictionary<int,T>.Add are explicit interface member implementations.

在某些情况下,接口成员的名称可能不适合实现类,在这种情况下,可以使用显式接口成员实现来实现接口成员。In some cases, the name of an interface member may not be appropriate for the implementing class, in which case the interface member may be implemented using explicit interface member implementation. 例如,实现文件抽象的类可能实现的 Close 成员函数具有释放文件资源的效果,并 Dispose IDisposable 使用显式接口成员实现实现接口的方法:A class implementing a file abstraction, for example, would likely implement a Close member function that has the effect of releasing the file resource, and implement the Dispose method of the IDisposable interface using explicit interface member implementation:

interface IDisposable
{
    void Dispose();
}

class MyFile: IDisposable
{
    void IDisposable.Dispose() {
        Close();
    }

    public void Close() {
        // Do what's necessary to close the file
        System.GC.SuppressFinalize(this);
    }
}

不能通过方法调用、属性访问或索引器访问中的完全限定名来访问显式接口成员实现。It is not possible to access an explicit interface member implementation through its fully qualified name in a method invocation, property access, or indexer access. 显式接口成员实现只能通过接口实例访问,在这种情况下,只需由其成员名称来引用。An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.

显式接口成员实现包含访问修饰符是编译时错误,它是包含修饰符、、或的编译时错误 abstract virtual override staticIt is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers abstract, virtual, override, or static.

显式接口成员实现具有与其他成员不同的可访问性特征。Explicit interface member implementations have different accessibility characteristics than other members. 由于显式接口成员实现决不能通过方法调用或属性访问中的完全限定名称进行访问,因此它们处于专用意义上。Because explicit interface member implementations are never accessible through their fully qualified name in a method invocation or a property access, they are in a sense private. 不过,由于它们可以通过接口实例进行访问,因此它们也是公共的。However, since they can be accessed through an interface instance, they are in a sense also public.

显式接口成员实现具有两个主要用途:Explicit interface member implementations serve two primary purposes:

  • 由于显式接口成员实现无法通过类或结构实例进行访问,因此它们允许从类或结构的公共接口中排除接口实现。Because explicit interface member implementations are not accessible through class or struct instances, they allow interface implementations to be excluded from the public interface of a class or struct. 当类或结构实现对该类或结构的使用者不感兴趣的内部接口时,此方法特别有用。This is particularly useful when a class or struct implements an internal interface that is of no interest to a consumer of that class or struct.
  • 显式接口成员实现允许用相同的签名消除接口成员的歧义。Explicit interface member implementations allow disambiguation of interface members with the same signature. 如果没有显式接口成员实现,类或结构将不可能具有相同签名和返回类型的接口成员的不同实现,因为该类或结构不可能在具有相同签名但具有不同返回类型的所有接口成员上具有任何实现。Without explicit interface member implementations it would be impossible for a class or struct to have different implementations of interface members with the same signature and return type, as would it be impossible for a class or struct to have any implementation at all of interface members with the same signature but with different return types.

为了使显式接口成员实现有效,类或结构必须在其基类列表中命名一个接口,该接口包含完全限定名、类型和参数类型与显式接口成员实现的完全限定名、类型和参数类型完全匹配的成员。For an explicit interface member implementation to be valid, the class or struct must name an interface in its base class list that contains a member whose fully qualified name, type, and parameter types exactly match those of the explicit interface member implementation. 因此,在下面的类中Thus, in the following class

class Shape: ICloneable
{
    object ICloneable.Clone() {...}
    int IComparable.CompareTo(object other) {...}    // invalid
}

IComparable.CompareTo由于未 IComparable 在的基类列表中列出,导致编译时错误中的声明,但不是的 Shape 基接口 ICloneablethe declaration of IComparable.CompareTo results in a compile-time error because IComparable is not listed in the base class list of Shape and is not a base interface of ICloneable. 同样,在声明中Likewise, in the declarations

class Shape: ICloneable
{
    object ICloneable.Clone() {...}
}

class Ellipse: Shape
{
    object ICloneable.Clone() {...}    // invalid
}

中的声明 ICloneable.Clone Ellipse 会导致编译时错误,因为 ICloneable 未在的基类列表中显式列出 Ellipsethe declaration of ICloneable.Clone in Ellipse results in a compile-time error because ICloneable is not explicitly listed in the base class list of Ellipse.

接口成员的完全限定名称必须引用声明该成员的接口。The fully qualified name of an interface member must reference the interface in which the member was declared. 因此,在声明中Thus, in the declarations

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

class TextBox: ITextBox
{
    void IControl.Paint() {...}
    void ITextBox.SetText(string text) {...}
}

的显式接口成员实现 Paint 必须编写为 IControl.Paintthe explicit interface member implementation of Paint must be written as IControl.Paint.

实现的接口的唯一性Uniqueness of implemented interfaces

对于所有可能的构造类型,泛型类型声明实现的接口必须保持唯一。The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. 如果没有此规则,则不可能为某些构造类型确定要调用的正确方法。Without this rule, it would be impossible to determine the correct method to call for certain constructed types. 例如,假设允许编写泛型类声明,如下所示:For example, suppose a generic class declaration were permitted to be written as follows:

interface I<T>
{
    void F();
}

class X<U,V>: I<U>, I<V>                    // Error: I<U> and I<V> conflict
{
    void I<U>.F() {...}
    void I<V>.F() {...}
}

这种情况下,不可能在以下情况下确定要执行的代码:Were this permitted, it would be impossible to determine which code to execute in the following case:

I<int> x = new X<int,int>();
x.F();

若要确定泛型类型声明的接口列表是否有效,请执行以下步骤:To determine if the interface list of a generic type declaration is valid, the following steps are performed:

  • 允许 L 使用泛型类、结构或接口声明中直接指定的接口的列表 CLet L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
  • 将添加到 L 中已存在的接口的任何基接口 LAdd to L any base interfaces of the interfaces already in L.
  • 从中删除所有重复项 LRemove any duplicates from L.
  • 如果从创建的任何可能的构造类型为,则在将 C 类型参数替换为之后, L 导致中的两个接口 L 相同,则的声明 C 无效。If any possible constructed type created from C would, after type arguments are substituted into L, cause two interfaces in L to be identical, then the declaration of C is invalid. 确定所有可能的构造类型时,不考虑约束声明。Constraint declarations are not considered when determining all possible constructed types.

在上面的类声明中 X ,接口列表 LI<U> 和组成 I<V>In the class declaration X above, the interface list L consists of I<U> and I<V>. 此声明无效,因为具有和的任何构造类型 U V 都将导致这两个接口的类型相同。The declaration is invalid because any constructed type with U and V being the same type would cause these two interfaces to be identical types.

不同继承级别中指定的接口可以统一:It is possible for interfaces specified at different inheritance levels to unify:

interface I<T>
{
    void F();
}

class Base<U>: I<U>
{
    void I<U>.F() {...}
}

class Derived<U,V>: Base<U>, I<V>    // Ok
{
    void I<V>.F() {...}
}

即使 Derived<U,V> 同时实现和,此代码仍 I<U> 有效 I<V>This code is valid even though Derived<U,V> implements both I<U> and I<V>. 代码The code

I<int> x = new Derived<int,int>();
x.F();

在中调用方法 Derived ,因为 Derived<int,int> 有效重新实现 I<int> (接口重新实现) 。invokes the method in Derived, since Derived<int,int> effectively re-implements I<int> (Interface re-implementation).

泛型方法的实现Implementation of generic methods

当泛型方法隐式实现接口方法时,为每个方法类型参数指定的约束必须在 (将任何接口类型参数替换为适当的类型) 参数(其中,方法类型参数由序号位置按从左到右)。When a generic method implicitly implements an interface method, the constraints given for each method type parameter must be equivalent in both declarations (after any interface type parameters are replaced with the appropriate type arguments), where method type parameters are identified by ordinal positions, left to right.

但是,当泛型方法显式实现接口方法时,实现方法不允许任何约束。When a generic method explicitly implements an interface method, however, no constraints are allowed on the implementing method. 相反,约束继承自接口方法Instead, the constraints are inherited from the interface method

interface I<A,B,C>
{
    void F<T>(T t) where T: A;
    void G<T>(T t) where T: B;
    void H<T>(T t) where T: C;
}

class C: I<object,C,string>
{
    public void F<T>(T t) {...}                    // Ok
    public void G<T>(T t) where T: C {...}         // Ok
    public void H<T>(T t) where T: string {...}    // Error
}

方法 C.F<T> 隐式实现 I<object,C,string>.F<T>The method C.F<T> implicitly implements I<object,C,string>.F<T>. 在这种情况下, C.F<T> 不需要 (也不允许) 指定约束, T:object 因为 object 是对所有类型参数的隐式约束。In this case, C.F<T> is not required (nor permitted) to specify the constraint T:object since object is an implicit constraint on all type parameters. 方法 C.G<T> 隐式实现 I<object,C,string>.G<T> ,因为在接口类型参数替换为相应的类型参数后,约束与接口中的约束匹配。The method C.G<T> implicitly implements I<object,C,string>.G<T> because the constraints match those in the interface, after the interface type parameters are replaced with the corresponding type arguments. 方法的约束 C.H<T> 是错误的,因为 string 在这种情况下,密封类型 () 不能用作约束。The constraint for method C.H<T> is an error because sealed types (string in this case) cannot be used as constraints. 省略约束也会导致错误,因为需要对隐式接口方法实现的约束匹配。Omitting the constraint would also be an error since constraints of implicit interface method implementations are required to match. 因此,无法隐式实现 I<object,C,string>.H<T>Thus, it is impossible to implicitly implement I<object,C,string>.H<T>. 此接口方法只能使用显式接口成员实现实现:This interface method can only be implemented using an explicit interface member implementation:

class C: I<object,C,string>
{
    ...

    public void H<U>(U u) where U: class {...}

    void I<object,C,string>.H<T>(T t) {
        string s = t;    // Ok
        H<T>(t);
    }
}

在此示例中,显式接口成员实现调用严格限制更弱的公共方法。In this example, the explicit interface member implementation invokes a public method having strictly weaker constraints. 请注意,从到的赋值在 t s 继承的约束时是有效的 T T:string ,即使此约束在源代码中不是可表示的。Note that the assignment from t to s is valid since T inherits a constraint of T:string, even though this constraint is not expressible in source code.

接口映射Interface mapping

类或结构必须提供类或结构的基类列表中列出的接口的所有成员的实现。A class or struct must provide implementations of all members of the interfaces that are listed in the base class list of the class or struct. 在实现类或结构中查找接口成员的实现的过程称为 接口映射The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.

类或结构的接口映射为的 C 基类列表中指定的每个接口的每个成员定位一个实现 CInterface mapping for a class or struct C locates an implementation for each member of each interface specified in the base class list of C. 特定接口成员的实现 I.M ,其中 I 是声明成员的接口 M ,通过检查每个类或结构( S 从开始 C ,并为的每个后续基类重复)来确定, C 直到找到匹配项为止:The implementation of a particular interface member I.M, where I is the interface in which the member M is declared, is determined by examining each class or struct S, starting with C and repeating for each successive base class of C, until a match is located:

  • 如果 S 包含与和匹配的显式接口成员实现的声明 I M ,则此成员是的实现 I.MIf S contains a declaration of an explicit interface member implementation that matches I and M, then this member is the implementation of I.M.
  • 否则,如果 S 包含与匹配的非静态公共成员的声明,则 M 此成员是的实现 I.MOtherwise, if S contains a declaration of a non-static public member that matches M, then this member is the implementation of I.M. 如果有多个成员匹配,则未指定哪个成员是的实现 I.MIf more than one member matches, it is unspecified which member is the implementation of I.M. 仅当 S 是一个构造类型,而泛型类型中声明的两个成员具有不同的签名,但类型参数使其签名完全相同时,才会发生这种情况。This situation can only occur if S is a constructed type where the two members as declared in the generic type have different signatures, but the type arguments make their signatures identical.

如果无法为的基类列表中指定的所有接口的所有成员找到实现,则会发生编译时错误 CA compile-time error occurs if implementations cannot be located for all members of all interfaces specified in the base class list of C. 请注意,接口的成员包括继承自基接口的成员。Note that the members of an interface include those members that are inherited from base interfaces.

出于接口映射的目的,类成员将 A 在以下情况下匹配接口成员 BFor purposes of interface mapping, a class member A matches an interface member B when:

  • AB 是方法,且和的名称、类型和形参列表 A B 完全相同。A and B are methods, and the name, type, and formal parameter lists of A and B are identical.
  • AB 是属性、和的名称和类型 A B 相同,并且具有与 A (相同的访问器 BA 如果它不是显式接口成员实现) 。A and B are properties, the name and type of A and B are identical, and A has the same accessors as B (A is permitted to have additional accessors if it is not an explicit interface member implementation).
  • AB 是事件,而和的名称和类型 A B 是相同的。A and B are events, and the name and type of A and B are identical.
  • AB 是索引器、和的类型参数列表和形参列表 A B 相同,并且 A 具有与 (相同的访问器, B A 如果它不是显式接口成员实现) 。A and B are indexers, the type and formal parameter lists of A and B are identical, and A has the same accessors as B (A is permitted to have additional accessors if it is not an explicit interface member implementation).

接口映射算法的显著含义如下:Notable implications of the interface mapping algorithm are:

  • 在确定实现接口成员的类或结构成员时,显式接口成员实现优先于同一个类或结构中的其他成员。Explicit interface member implementations take precedence over other members in the same class or struct when determining the class or struct member that implements an interface member.
  • 非公共成员和静态成员均参与接口映射。Neither non-public nor static members participate in interface mapping.

示例中In the example

interface ICloneable
{
    object Clone();
}

class C: ICloneable
{
    object ICloneable.Clone() {...}
    public object Clone() {...}
}

ICloneable.Clone 成员 C 成为中的实现, Clone ICloneable 因为显式接口成员实现优先于其他成员。the ICloneable.Clone member of C becomes the implementation of Clone in ICloneable because explicit interface member implementations take precedence over other members.

如果类或结构实现了两个或更多个接口,其中包含具有相同名称、类型和参数类型的成员,则可以将其中的每个接口成员映射到单个类或结构成员。If a class or struct implements two or more interfaces containing a member with the same name, type, and parameter types, it is possible to map each of those interface members onto a single class or struct member. 例如For example

interface IControl
{
    void Paint();
}

interface IForm
{
    void Paint();
}

class Page: IControl, IForm
{
    public void Paint() {...}
}

此处, Paint 和的方法 IControl IForm 映射到 Paint 中的方法 PageHere, the Paint methods of both IControl and IForm are mapped onto the Paint method in Page. 当然,对于这两种方法,还可以使用单独的显式接口成员实现。It is of course also possible to have separate explicit interface member implementations for the two methods.

如果类或结构实现的接口包含隐藏成员,则必须通过显式接口成员实现实现某些成员。If a class or struct implements an interface that contains hidden members, then some members must necessarily be implemented through explicit interface member implementations. 例如For example

interface IBase
{
    int P { get; }
}

interface IDerived: IBase
{
    new int P();
}

此接口的实现需要至少一个显式接口成员实现,并采用以下形式之一An implementation of this interface would require at least one explicit interface member implementation, and would take one of the following forms

class C: IDerived
{
    int IBase.P { get {...} }
    int IDerived.P() {...}
}

class C: IDerived
{
    public int P { get {...} }
    int IDerived.P() {...}
}

class C: IDerived
{
    int IBase.P { get {...} }
    public int P() {...}
}

如果类实现多个具有相同基接口的接口,则基接口只能有一个实现。When a class implements multiple interfaces that have the same base interface, there can be only one implementation of the base interface. 示例中In the example

interface IControl
{
    void Paint();
}

interface ITextBox: IControl
{
    void SetText(string text);
}

interface IListBox: IControl
{
    void SetItems(string[] items);
}

class ComboBox: IControl, ITextBox, IListBox
{
    void IControl.Paint() {...}
    void ITextBox.SetText(string text) {...}
    void IListBox.SetItems(string[] items) {...}
}

对于 IControl 基类列表中命名的、 IControl 继承的 ITextBoxIControl 由继承 IListBox 的,不能具有单独的实现。it is not possible to have separate implementations for the IControl named in the base class list, the IControl inherited by ITextBox, and the IControl inherited by IListBox. 的确,这些接口没有单独标识的概念。Indeed, there is no notion of a separate identity for these interfaces. 而是的实现 ITextBoxIListBox 共享的相同实现 IControl ,并且 ComboBox 只被视为实现三个接口: IControlITextBoxIListBoxRather, the implementations of ITextBox and IListBox share the same implementation of IControl, and ComboBox is simply considered to implement three interfaces, IControl, ITextBox, and IListBox.

基类的成员参与接口映射。The members of a base class participate in interface mapping. 示例中In the example

interface Interface1
{
    void F();
}

class Class1
{
    public void F() {}
    public void G() {}
}

class Class2: Class1, Interface1
{
    new public void G() {}
}

FClass1 的实现中使用了中的方法 Class2 Interface1the method F in Class1 is used in Class2's implementation of Interface1.

接口实现继承Interface implementation inheritance

类继承其基类提供的所有接口实现。A class inherits all interface implementations provided by its base classes.

如果没有显式 重新实现 接口,派生类将无法以任何方式更改它从其基类继承的接口映射。Without explicitly re-implementing an interface, a derived class cannot in any way alter the interface mappings it inherits from its base classes. 例如,在声明中For example, in the declarations

interface IControl
{
    void Paint();
}

class Control: IControl
{
    public void Paint() {...}
}

class TextBox: Control
{
    new public void Paint() {...}
}

Paint中的方法 TextBox 隐藏 Paint 中的方法 Control ,但它不会更改到的映射 Control.Paint IControl.Paint ,并且 Paint 通过类实例和接口实例的调用将具有以下效果:the Paint method in TextBox hides the Paint method in Control, but it does not alter the mapping of Control.Paint onto IControl.Paint, and calls to Paint through class instances and interface instances will have the following effects

Control c = new Control();
TextBox t = new TextBox();
IControl ic = c;
IControl it = t;
c.Paint();            // invokes Control.Paint();
t.Paint();            // invokes TextBox.Paint();
ic.Paint();           // invokes Control.Paint();
it.Paint();           // invokes Control.Paint();

但是,当接口方法映射到类中的虚方法时,派生类可以重写虚拟方法并更改接口的实现。However, when an interface method is mapped onto a virtual method in a class, it is possible for derived classes to override the virtual method and alter the implementation of the interface. 例如,将上述声明重写到For example, rewriting the declarations above to

interface IControl
{
    void Paint();
}

class Control: IControl
{
    public virtual void Paint() {...}
}

class TextBox: Control
{
    public override void Paint() {...}
}

现在会看到以下效果the following effects will now be observed

Control c = new Control();
TextBox t = new TextBox();
IControl ic = c;
IControl it = t;
c.Paint();            // invokes Control.Paint();
t.Paint();            // invokes TextBox.Paint();
ic.Paint();           // invokes Control.Paint();
it.Paint();           // invokes TextBox.Paint();

由于不能将显式接口成员实现声明为虚拟的,因此不能重写显式接口成员实现。Since explicit interface member implementations cannot be declared virtual, it is not possible to override an explicit interface member implementation. 但是,显式接口成员实现可以调用另一个方法,并且可以将另一个方法声明为虚拟,以允许派生类重写它。However, it is perfectly valid for an explicit interface member implementation to call another method, and that other method can be declared virtual to allow derived classes to override it. 例如For example

interface IControl
{
    void Paint();
}

class Control: IControl
{
    void IControl.Paint() { PaintControl(); }
    protected virtual void PaintControl() {...}
}

class TextBox: Control
{
    protected override void PaintControl() {...}
}

在这里,从派生的类 Control 可以 IControl.Paint 通过重写方法来专用化的实现 PaintControlHere, classes derived from Control can specialize the implementation of IControl.Paint by overriding the PaintControl method.

接口重新实现Interface re-implementation

允许继承接口实现的类通过将其包含在基类列表中来 重新实现 接口。A class that inherits an interface implementation is permitted to re-implement the interface by including it in the base class list.

接口的重新实现与接口的初始实现完全相同的接口映射规则。A re-implementation of an interface follows exactly the same interface mapping rules as an initial implementation of an interface. 因此,继承的接口映射对为接口的重新实现而建立的接口映射不起任何作用。Thus, the inherited interface mapping has no effect whatsoever on the interface mapping established for the re-implementation of the interface. 例如,在声明中For example, in the declarations

interface IControl
{
    void Paint();
}

class Control: IControl
{
    void IControl.Paint() {...}
}

class MyControl: Control, IControl
{
    public void Paint() {}
}

Control映射到的事实 IControl.Paint Control.IControl.Paint 不会影响映射到的中的重新实现 MyControl IControl.Paint MyControl.Paintthe fact that Control maps IControl.Paint onto Control.IControl.Paint doesn't affect the re-implementation in MyControl, which maps IControl.Paint onto MyControl.Paint.

继承的公共成员声明和继承的显式接口成员声明参与了重新实现的接口的接口映射过程。Inherited public member declarations and inherited explicit interface member declarations participate in the interface mapping process for re-implemented interfaces. 例如For example

interface IMethods
{
    void F();
    void G();
    void H();
    void I();
}

class Base: IMethods
{
    void IMethods.F() {}
    void IMethods.G() {}
    public void H() {}
    public void I() {}
}

class Derived: Base, IMethods
{
    public void F() {}
    void IMethods.H() {}
}

此处的实现将 IMethods Derived 接口方法映射到 Derived.FBase.IMethods.GDerived.IMethods.HBase.IHere, the implementation of IMethods in Derived maps the interface methods onto Derived.F, Base.IMethods.G, Derived.IMethods.H, and Base.I.

当类实现接口时,它还隐式实现该接口的所有基接口。When a class implements an interface, it implicitly also implements all of that interface's base interfaces. 同样,接口的重新实现也隐式实现了所有接口的基接口。Likewise, a re-implementation of an interface is also implicitly a re-implementation of all of the interface's base interfaces. 例如For example

interface IBase
{
    void F();
}

interface IDerived: IBase
{
    void G();
}

class C: IDerived
{
    void IBase.F() {...}
    void IDerived.G() {...}
}

class D: C, IDerived
{
    public void F() {...}
    public void G() {...}
}

这里,还重新实现了,并将 IDerived IBase 映射 IBase.FD.FHere, the re-implementation of IDerived also re-implements IBase, mapping IBase.F onto D.F.

抽象类和接口Abstract classes and interfaces

与非抽象类一样,抽象类必须提供类的基类列表中列出的接口的所有成员的实现。Like a non-abstract class, an abstract class must provide implementations of all members of the interfaces that are listed in the base class list of the class. 但允许抽象类将接口方法映射到抽象方法。However, an abstract class is permitted to map interface methods onto abstract methods. 例如For example

interface IMethods
{
    void F();
    void G();
}

abstract class C: IMethods
{
    public abstract void F();
    public abstract void G();
}

此处, IMethods 映射 FG 抽象方法的实现必须在派生自的非抽象类中重写 CHere, the implementation of IMethods maps F and G onto abstract methods, which must be overridden in non-abstract classes that derive from C.

请注意,显式接口成员实现不能是抽象的,但当然允许显式接口成员实现调用抽象方法。Note that explicit interface member implementations cannot be abstract, but explicit interface member implementations are of course permitted to call abstract methods. 例如For example

interface IMethods
{
    void F();
    void G();
}

abstract class C: IMethods
{
    void IMethods.F() { FF(); }
    void IMethods.G() { GG(); }
    protected abstract void FF();
    protected abstract void GG();
}

此处,从派生的非抽象类 C 需要重写 FFGG ,从而提供的实际实现 IMethodsHere, non-abstract classes that derive from C would be required to override FF and GG, thus providing the actual implementation of IMethods.