接口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
internal
和 private
修饰符控制接口的可访问性。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_annotation 。The 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 parameterT
是一个带有输出不安全元素类型的数组类型T
is an array type with an output-unsafe element typeT
是从泛型类型构造的接口或委托类型,S<A1,...,Ak>
S<X1,...,Xk>
其中至少Ai
包含以下项之一:T
is an interface or delegate typeS<A1,...,Ak>
constructed from a generic typeS<X1,...,Xk>
where for at least oneAi
one of the following holds:Xi
是协变或固定,并且Ai
是输出不安全的。Xi
is covariant or invariant andAi
is output-unsafe.Xi
为逆变或固定,并且Ai
是输入安全的。Xi
is contravariant or invariant andAi
is input-safe.
T
如果包含以下内容之一,则类型为 输入-不安全:A type T
is input-unsafe if one of the following holds:
T
是协变类型参数T
is a covariant type parameterT
是具有输入不安全元素类型的数组类型T
is an array type with an input-unsafe element typeT
是从泛型类型构造的接口或委托类型,S<A1,...,Ak>
S<X1,...,Xk>
其中至少Ai
包含以下项之一:T
is an interface or delegate typeS<A1,...,Ak>
constructed from a generic typeS<X1,...,Xk>
where for at least oneAi
one of the following holds:Xi
是协变或固定的,并且Ai
是输入不安全的。Xi
is covariant or invariant andAi
is input-unsafe.Xi
为逆变或固定,并且Ai
是输出不安全的。Xi
is contravariant or invariant andAi
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``Bi
Xi
is covariant and an implicit reference or identity conversion exists fromAi
toBi
Xi
为逆变,并且存在从到的隐式引用或标识转换Bi``Ai
Xi
is contravariant and an implicit reference or identity conversion exists fromBi
toAi
Xi
是固定的,存在从到的标识转换Ai``Bi
Xi
is invariant and an identity conversion exists fromAi
toBi
基接口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 中指定或接口是编译时错误 public
。For 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 {}
的基接口 IComboBox
是 IControl
、 ITextBox
和 IListBox
。the base interfaces of IComboBox
are IControl
, ITextBox
, and IListBox
.
换言之, IComboBox
以上接口继承成员 SetText
和 SetItems
Paint
。In 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. 特别是,不能用修饰符 abstract
、 public
、 protected
、、、、 internal
private
virtual
override
或 static
声明接口成员。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_declaration:The 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
out
。In 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 byref
andout
. - 属性或事件的名称必须不同于在同一接口中声明的所有其他成员的名称。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. 通过删除修饰符,可取消显示此警告 new
。This 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 . 此外,任何 out
或 ref
形参类型也必须是输出安全类型。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.Add
。Similarly 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.F
被 ILeft.F
成员隐藏。the IBase.F
member is hidden by the ILeft.F
member. d.F(1)
这样 ILeft.F
,调用会选择,即使 IBase.F
似乎不会隐藏在导致的访问路径中 IRight
。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
.
在多继承接口中隐藏的直观规则是:如果某个成员在任何访问路径中都隐藏,则它会在所有访问路径中隐藏。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
IBase
。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
.
完全限定的接口成员名称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);
}
的完全限定名 Paint
为 IControl.Paint
,的完全限定名 SetText
为 ITextBox.SetText
。the fully qualified name of Paint
is IControl.Paint
and the fully qualified name of SetText
is ITextBox.SetText
.
在上面的示例中,不能将 Paint
作为引用 ITextBox.Paint
。In 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();
}
}
此处,方法的完全限定名 Clone
是 System.ICloneable.Clone
。Here, 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
实现 IControl
和 ITextBox
。Here, 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>.this
和 IDictionary<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
static
。It 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
基接口 ICloneable
。the 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
未在的基类列表中显式列出 Ellipse
。the 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.Paint
。the 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
使用泛型类、结构或接口声明中直接指定的接口的列表C
。LetL
be the list of interfaces directly specified in a generic class, struct, or interface declarationC
. - 将添加到
L
中已存在的接口的任何基接口L
。Add toL
any base interfaces of the interfaces already inL
. - 从中删除所有重复项
L
。Remove any duplicates fromL
. - 如果从创建的任何可能的构造类型为,则在将
C
类型参数替换为之后,L
导致中的两个接口L
相同,则的声明C
无效。If any possible constructed type created fromC
would, after type arguments are substituted intoL
, cause two interfaces inL
to be identical, then the declaration ofC
is invalid. 确定所有可能的构造类型时,不考虑约束声明。Constraint declarations are not considered when determining all possible constructed types.
在上面的类声明中 X
,接口列表 L
由 I<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
基类列表中指定的每个接口的每个成员定位一个实现 C
。Interface 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.M
。IfS
contains a declaration of an explicit interface member implementation that matchesI
andM
, then this member is the implementation ofI.M
. - 否则,如果
S
包含与匹配的非静态公共成员的声明,则M
此成员是的实现I.M
。Otherwise, ifS
contains a declaration of a non-static public member that matchesM
, then this member is the implementation ofI.M
. 如果有多个成员匹配,则未指定哪个成员是的实现I.M
。If more than one member matches, it is unspecified which member is the implementation ofI.M
. 仅当S
是一个构造类型,而泛型类型中声明的两个成员具有不同的签名,但类型参数使其签名完全相同时,才会发生这种情况。This situation can only occur ifS
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.
如果无法为的基类列表中指定的所有接口的所有成员找到实现,则会发生编译时错误 C
。A 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
在以下情况下匹配接口成员 B
:For purposes of interface mapping, a class member A
matches an interface member B
when:
A
和B
是方法,且和的名称、类型和形参列表A
B
完全相同。A
andB
are methods, and the name, type, and formal parameter lists ofA
andB
are identical.A
和B
是属性、和的名称和类型A
B
相同,并且具有与A
(相同的访问器B
,A
如果它不是显式接口成员实现) 。A
andB
are properties, the name and type ofA
andB
are identical, andA
has the same accessors asB
(A
is permitted to have additional accessors if it is not an explicit interface member implementation).A
和B
是事件,而和的名称和类型A
B
是相同的。A
andB
are events, and the name and type ofA
andB
are identical.A
和B
是索引器、和的类型参数列表和形参列表A
B
相同,并且A
具有与 (相同的访问器,B
A
如果它不是显式接口成员实现) 。A
andB
are indexers, the type and formal parameter lists ofA
andB
are identical, andA
has the same accessors asB
(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
中的方法 Page
。Here, 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
继承的 ITextBox
和 IControl
由继承 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. 而是的实现 ITextBox
和 IListBox
共享的相同实现 IControl
,并且 ComboBox
只被视为实现三个接口: IControl
、 ITextBox
和 IListBox
。Rather, 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() {}
}
F
在 Class1
的实现中使用了中的方法 Class2
Interface1
。the 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
通过重写方法来专用化的实现 PaintControl
。Here, 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.Paint
。the 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.F
、 Base.IMethods.G
、 Derived.IMethods.H
和 Base.I
。Here, 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.F
到 D.F
。Here, 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
映射 F
和 G
抽象方法的实现必须在派生自的非抽象类中重写 C
。Here, 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
需要重写 FF
和 GG
,从而提供的实际实现 IMethods
。Here, non-abstract classes that derive from C
would be required to override FF
and GG
, thus providing the actual implementation of IMethods
.