インターフェイス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_modifiers (修飾子をインターフェイス) と省略可能なその後partialの後に、キーワード修飾子interface識別子インターフェイスの名前を示す続けて、省略可能なvariant_type_parameter_list仕様 (バリアント型パラメーター リスト) と省略可能なその後interface_base仕様 (基本インターフェイス) と省略可能なその後type_parameter_constraints_clauses 仕様 (パラメーターの制約入力)、続けて、 interface_body (インターフェイス本体)、セミコロンで必要に応じてその後にします。An interface_declaration consists of an optional set of attributes (Attributes), followed by an optional set of interface_modifiers (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_clauses 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. 指定します、インターフェイスが、同じ名前で、継承されたメンバーを非表示にする」の説明に従ってnew 修飾子します。It specifies that the interface hides an inherited member by the same name, as described in The new modifier.

publicprotectedinternal、および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. 指定された規則に従って、それを囲む名前空間または型の宣言内に同じ名前を持つ複数の部分的なインターフェイス宣言は、フォームの 1 つのインターフェイスの宣言に結合、部分型します。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_lists は省略可能なvariance_annotation型パラメーターごとにします。The difference from ordinary type_parameter_lists 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>少なくとも 1 つの whereAi次のいずれかを保持します。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>少なくとも 1 つの whereAi次のいずれかを保持します。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.

型が出力セーフ出力 unsafe でない場合、入力の安全なない入力の安全でない場合。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. この暗黙の定義を終了します (暗黙的な変換) と明示的な変換 (明示的な変換) ことを次のように定義されている分散でもの概念の使用します。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>、および各バリアント型パラメーターの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 共変およびから暗黙の参照または id 変換が存在するAiBiXi is covariant and an implicit reference or identity conversion exists from Ai to Bi
  • Xi 反変、暗黙的な参照またはから id 変換が存在するBiAiXi is contravariant and an implicit reference or identity conversion exists from Bi to Ai
  • Xi 不変性は、id からの変換が存在するAiBiXi is invariant and an identity conversion exists from Ai to Bi

基底インターフェイスBase interfaces

インターフェイスと呼ばれる、0 個以上のインターフェイス型から継承できます、基底インターフェイスの明示的なのインターフェイス。An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. インターフェイスの 1 つまたは複数の明示的な基本インターフェイスの場合、そのインターフェイスの宣言インターフェイス識別子の後にコロンとコンマ区切り基底インターフェイスの種類の一覧。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_basepublicインターフェイス。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 {}

インターフェイスの基本IComboBoxIControlITextBox、およびIListBoxします。the base interfaces of IComboBox are IControl, ITextBox, and IListBox.

つまり、IComboBox上記のインターフェイス メンバーを継承するSetTextSetItemsだけでなく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
    ;

インターフェイスの宣言には、0 個以上のメンバーを宣言できます。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. 具体的には、修飾子を使用してインターフェイス メンバーを宣言することはできませんabstractpublicprotectedinternalprivatevirtualoverride、または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; }
}

メンバーの可能な種類の 1 つずつ含むインターフェイスを宣言します。メソッド、プロパティ、イベント、およびインデクサーです。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_member_declarationですぐに格納されているinterface_declarationこの宣言領域に新しいメンバーを導入します。An interface_declaration creates a new declaration space (Declarations), and the interface_member_declarations immediately contained by the interface_declaration introduce new members into this declaration space. 次の規則に適用されますinterface_member_declaration: %sThe following rules apply to interface_member_declarations:

  • メソッドの名前は、すべてのプロパティと同じインターフェイスで宣言されたイベントの名前とは異なる必要があります。The name of a method must differ from the names of all properties and events declared in the same interface. さらに、署名 (シグネチャとオーバー ロード) のメソッドと同じインターフェイスで宣言されている他のすべてのメソッドのシグネチャは異なるし、同じインターフェイスで宣言されている 2 つの方法で署名がない可能性がありますがのみが異なるrefoutします。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 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. 削除することによってこの警告が抑制され、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: %sInterface methods are declared using interface_method_declarations:

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: %sInterface properties are declared using interface_property_declarations:

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: %sInterface events are declared using interface_event_declarations:

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: %sInterface indexers are declared using interface_indexer_declarations:

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.MI[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.

厳密にはインターフェイスの単一継承 (継承チェーン内の各インターフェイスは、正確に 0 個または 1 つの直接基底インターフェイスを持つ)、メンバー検索の効果 (メンバー ルックアップ)、メソッドの呼び出し (メソッドの呼び出し)、およびインデクサー アクセス (インデクサー アクセス) ルールはまったく同じクラスと構造体です。メンバーの非表示には、同じ名前またはシグネチャを持つ派生メンバーを少なくする強い派生します。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. ただし、多重継承インターフェイスでは、2 つに、あいまいさが発生することがまたは以上の関連付けられていない基本インターフェイスが同じ名前またはシグネチャを持つメンバーを宣言します。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
    }
}

最初の 2 つのステートメントのコンパイル時エラーが発生するため、メンバー検索 (メンバー検索) のCountIListCounterがあいまいです。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. 明示的なキャストが挿入されると、メソッドとなるに 1 つのみの候補があります。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を通じて潜在顧客のアクセス パスで非表示にしないよう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. からのアクセス パスIDerivedILeftIBaseを非表示にIBase.Fからのアクセス パスで、メンバーは非表示もIDerivedIRightIBaseします。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);
}

完全修飾名PaintIControl.Paintとの完全修飾名SetTextITextBox.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両方を実装IControlITextBoxします。Here, class TextBox implements both IControl and ITextBox.

クラスとCC から派生したすべてのクラス、インターフェイスを実装するインターフェイスを暗黙的に実装も直接します。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.

アクセス修飾子を含めるには、明示的なインターフェイス メンバーの実装と、コンパイル時エラーし、修飾子を含めると、コンパイル時エラー abstractvirtualoverride、または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.

明示的なインターフェイス メンバーの実装では、2 つの主な目的を果たします。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.CloneEllipseため、コンパイル時エラー結果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します。Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
  • 追加L任意の基本インターフェイスのインターフェイスを既にLします。Add to L any base interfaces of the interfaces already in L.
  • すべての重複を削除Lします。Remove any duplicates from L.
  • 可能性のあるすべての構築型から作成された場合Cは、型引数に置き換え後L、2 つのインターフェイスで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インターフェイス リストの上Lから成るI<U>I<V>します。In the class declaration X above, the interface list L consists of I<U> and I<V>. いずれかを持つ型が構築されたため、宣言は無効ですUVこれら 2 つのインターフェイスと同じ型にすることによって、同じ型の中します。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>、sealed 型であるために、エラー (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. なおから代入されたts以降が正しく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と一致する明示的なインターフェイス メンバーの実装の宣言を含むIM、このメンバーは、実装のI.Mします。If 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.Mします。Otherwise, if S contains a declaration of a non-static public member that matches M, then this member is the implementation of I.M. メンバーの実装は、1 つのメンバーの一致よりも多く指定がない場合I.Mします。If more than one member matches, it is unspecified which member is the implementation of I.M. このような状況はできる場合にのみ発生Sが構築された型をジェネリック型で宣言されている 2 つのメンバーが異なるシグネチャを持つが、型引数を指定すること、署名は同じです。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.

コンパイル時エラーは、実装は、の基底クラス リストで指定されたすべてのインターフェイスのすべてのメンバーが見つからない場合に発生します。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メソッド、および、名前、種類、および仮パラメーター リストABは同じです。A and B are methods, and the name, type, and formal parameter lists of A and B are identical.
  • A B 、プロパティ、名前および種類のAB同じですとAと同じアクセサーを持つB(A明示的なインターフェイスでない場合は、追加のアクセサーを持つことができますメンバーの実装の場合)。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).
  • A Bイベントは、名前と種類のABは同じです。A and B are events, and the name and type of A and B are identical.
  • A Bインデクサーでは、型と仮パラメーター リストはAB同じですと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の実装になりますCloneICloneable理由は、明示的なインターフェイス メンバーの実装が他のメンバーより優先順位。the ICloneable.Clone member of C becomes the implementation of Clone in ICloneable because explicit interface member implementations take precedence over other members.

同じ名前、種類、およびパラメーターの型を持つメンバーを格納している以上のインターフェイスをクラスまたは構造体は 2 つを実装している場合は、1 つのクラスまたは構造体メンバー上にこれらのインターフェイス メンバーの各をマップすること勧めします。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の両方のメソッドIControlIFormにマップされて、PaintメソッドPageします。Here, the Paint methods of both IControl and IForm are mapped onto the Paint method in Page. もちろんも 2 つのメソッドの別の明示的なインターフェイス メンバーの実装を含めることは可能です。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();
}

このインターフェイスの実装に少なくとも 1 つの明示的なインターフェイス メンバーの実装では、必要し、なります。 形式は次のいずれか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() {...}
}

クラスは、同じ基本インターフェイスを持つ複数のインターフェイスを実装するときに、基本インターフェイスの 1 つだけの実装があります。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によって継承IListBoxit 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. 実際には、これらのインターフェイスに別々 の id の概念はありません。Indeed, there is no notion of a separate identity for these interfaces. 実装ではなく、ITextBoxIListBoxの同じ実装を共有IControl、およびComboBoxは単に 3 つのインターフェイスを実装すると見なされますIControlITextBox、および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() {}
}

メソッドFClass1で使用されて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.PaintIControl.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();

明示的なインターフェイス メンバーの実装を virtual と宣言することはできません、ために、明示的なインターフェイス メンバーの実装をオーバーライドすることはできません。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.PaintControl.IControl.Paintで再実装には影響しませんMyControl、マップをIControl.PaintMyControl.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() {}
}

ここでは、の実装IMethodsDerivedにインターフェイス メソッドのマップDerived.FBase.IMethods.GDerived.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.FD.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マップFGを抽象メソッドは、上にから派生した非抽象クラスでオーバーライドする必要があります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をオーバーライドする必要がありますFFGG、したがっての実際の実装を提供するIMethodsします。Here, non-abstract classes that derive from C would be required to override FF and GG, thus providing the actual implementation of IMethods.