InterfacesInterfaces

Une interface définit un contrat.An interface defines a contract. Une classe ou un struct qui implémente une interface doit adhérer à ce contrat.A class or struct that implements an interface must adhere to its contract. Une interface peut hériter de plusieurs interfaces de base, et une classe ou un struct peut implémenter plusieurs interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

Interfaces peuvent contenir des méthodes, propriétés, événements et indexeurs.Interfaces can contain methods, properties, events, and indexers. L’interface elle-même ne fournit pas d’implémentations pour les membres qu’elle définit.The interface itself does not provide implementations for the members that it defines. L’interface spécifie simplement les membres qui doivent être fournis par les classes ou structs qui implémentent l’interface.The interface merely specifies the members that must be supplied by classes or structs that implement the interface.

Déclarations d’interfaceInterface declarations

Un interface_declaration est un type_declaration (les déclarations de Type) qui déclare un nouveau type d’interface.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 ';'?
    ;

Un interface_declaration se compose d’un ensemble facultatif de attributs (attributs), suivi d’un ensemble facultatif de interface_modifiers (modificateurs d’Interface), suivie éventuellement d’un partial modificateur, suivi par le mot clé interface et un identificateur qui nomme l’interface, suivi d’un texte facultatif variant_type_parameter_list spécification (listes de paramètres de type Variant), suivie éventuellement d’un interface_base spécification (interfaces de Base), suivie éventuellement d’un type_parameter_constraints_clausespécification s (les contraintes de paramètre de Type) , suivie d’une interface_body (corps de l’Interface), éventuellement suivi par un point-virgule.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.

Modificateurs d’interfaceInterface modifiers

Un interface_declaration peut éventuellement inclure une séquence de modificateurs d’interface :An interface_declaration may optionally include a sequence of interface modifiers:

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

Il s’agit d’une erreur de compilation pour le même modificateur apparaît plusieurs fois dans une déclaration d’interface.It is a compile-time error for the same modifier to appear multiple times in an interface declaration.

Le new modificateur est autorisé uniquement sur les interfaces définies dans une classe.The new modifier is only permitted on interfaces defined within a class. Il spécifie que l’interface masque un membre hérité par le même nom, comme décrit dans le nouveau modificateur.It specifies that the interface hides an inherited member by the same name, as described in The new modifier.

Le public, protected, internal, et private modificateurs contrôlent l’accessibilité de l’interface.The public, protected, internal, and private modifiers control the accessibility of the interface. En fonction du contexte dans lequel la déclaration d’interface se produit, seuls certains de ces modificateurs peuvent être autorisée (accessibilité déclarée).Depending on the context in which the interface declaration occurs, only some of these modifiers may be permitted (Declared accessibility).

Modificateur partielPartial modifier

Le partial modificateur indique que cela interface_declaration est une déclaration de type partiel.The partial modifier indicates that this interface_declaration is a partial type declaration. Plusieurs déclarations partielles interface portant le même nom dans une déclaration d’espace de noms ou type englobant combinent à la déclaration d’une interface de formulaire, conformément aux règles spécifiées dans types partiels.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.

Listes de paramètres de type VariantVariant type parameter lists

Listes de paramètres de type Variant peuvent se produire uniquement sur les types d’interface et délégué.Variant type parameter lists can only occur on interface and delegate types. La différence d’ordinaire type_parameter_lists est facultatif variance_annotation sur chaque paramètre de type.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'
    ;

Si l’annotation de variance est out, le paramètre de type est dite covariant.If the variance annotation is out, the type parameter is said to be covariant. Si l’annotation de variance est in, le paramètre de type est dite contravariant.If the variance annotation is in, the type parameter is said to be contravariant. S’il n’existe aucune annotation de variance, le paramètre de type est dite invariant.If there is no variance annotation, the type parameter is said to be invariant.

Dans l’exempleIn the example

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

X est covariant, Y est contravariant et Z est invariant.X is covariant, Y is contravariant and Z is invariant.

Sécurité de varianceVariance safety

L’occurrence des annotations de variance dans la liste de paramètres de type d’un type restreint les emplacements où les types peuvent se produire dans la déclaration de type.The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration.

Un type T est sortie non sécurisés si dont l’un des éléments suivants :A type T is output-unsafe if one of the following holds:

  • T est un paramètre de type contravariantT is a contravariant type parameter
  • T est un type de tableau avec un type d’élément de sortie non sécurisésT is an array type with an output-unsafe element type
  • T est un type d’interface ou un délégué S<A1,...,Ak> construit à partir d’un type générique S<X1,...,Xk> where pour au moins un Ai dont l’un des éléments suivants :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 est covariant ou invariants et Ai n’est pas sûre de sortie.Xi is covariant or invariant and Ai is output-unsafe.
    • Xi est contravariant ou invariant et Ai est entrée-safe.Xi is contravariant or invariant and Ai is input-safe.

Un type T est entrée non fiables si dont l’un des éléments suivants :A type T is input-unsafe if one of the following holds:

  • T est un paramètre de type covariantT is a covariant type parameter
  • T est un type de tableau avec un type d’élément d’entrée non fiablesT is an array type with an input-unsafe element type
  • T est un type d’interface ou un délégué S<A1,...,Ak> construit à partir d’un type générique S<X1,...,Xk> where pour au moins un Ai dont l’un des éléments suivants :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 est covariant ou invariants et Ai est entrée non fiables.Xi is covariant or invariant and Ai is input-unsafe.
    • Xi est contravariant ou invariant et Ai n’est pas sûre de sortie.Xi is contravariant or invariant and Ai is output-unsafe.

Intuitivement, un type non sécurisé de sortie est interdit dans une position de sortie, et un type d’entrée non fiables est interdit dans une position d’entrée.Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position.

Est un type sortie-safe s’il n’est pas dangereux de la sortie, et entrée-safe si elle n’est pas entrée non fiables.A type is output-safe if it is not output-unsafe, and input-safe if it is not input-unsafe.

Conversion de varianceVariance conversion

Les annotations de variance vise à fournir pour les conversions des types interface et délégué plus modérées (mais toujours type sécurisé).The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. À cette fin les définitions d’implicite (conversions implicites) et les conversions explicites (conversions explicites) rendre utilisent la notion de la convertibilité de variance, qui est définie comme suit :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:

Un type T<A1,...,An> est convertible en variance en un type T<B1,...,Bn> si T est une interface ou un type délégué déclaré avec les paramètres de type variant T<X1,...,Xn>et pour chaque paramètre de type variant Xi une des opérations suivantes contient :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 est covariant et il existe une conversion implicite de l’identité ou de référence à partir de Ai à BiXi is covariant and an implicit reference or identity conversion exists from Ai to Bi
  • Xi est contravariant et une référence implicite ou la conversion d’identité existe à partir de Bi à AiXi is contravariant and an implicit reference or identity conversion exists from Bi to Ai
  • Xi est invariant et une identité conversion existe entre Ai à BiXi is invariant and an identity conversion exists from Ai to Bi

Interfaces de baseBase interfaces

Une interface peut hériter de zéro ou plusieurs types d’interface, qui sont appelés les interfaces de base explicites de l’interface.An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. Lorsqu’une interface possède une ou plusieurs interfaces de base explicites, dans la déclaration de cette interface, l’identificateur d’interface est suivie par un signe deux-points et d’une virgule liste séparée par des types d’interface de base.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
    ;

Pour un type interface construite, les interfaces de base explicites sont formés en prenant les déclarations d’interface de base explicite sur la déclaration de type générique et en remplaçant, pour chaque type_parameter dans l’interface de base déclaration, correspondants type_argument du type construit.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.

Les interfaces de base explicites d’une interface doivent être au moins aussi accessibles que l’interface elle-même (contraintes d’accessibilité).The explicit base interfaces of an interface must be at least as accessible as the interface itself (Accessibility constraints). Par exemple, il est une erreur de compilation pour spécifier un private ou internal interface dans le interface_base d’un public interface.For example, it is a compile-time error to specify a private or internal interface in the interface_base of a public interface.

Il s’agit d’une erreur de compilation pour qu’une interface hérite directement ou indirectement d’elle-même.It is a compile-time error for an interface to directly or indirectly inherit from itself.

Le interfaces de base d’une interface sont les interfaces de base explicites et leurs interfaces de base.The base interfaces of an interface are the explicit base interfaces and their base interfaces. En d’autres termes, le jeu d’interfaces de base est la fermeture transitive complète des interfaces de base explicites, leurs interfaces de base explicites et ainsi de suite.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. Une interface hérite de tous les membres de ses interfaces de base.An interface inherits all members of its base interfaces. Dans l’exempleIn the example

interface IControl
{
    void Paint();
}

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

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

interface IComboBox: ITextBox, IListBox {}

les interfaces de base de IComboBox sont IControl, ITextBox, et IListBox.the base interfaces of IComboBox are IControl, ITextBox, and IListBox.

En d’autres termes, le IComboBox interface ci-dessus hérite des membres SetText et SetItems ainsi que Paint.In other words, the IComboBox interface above inherits members SetText and SetItems as well as Paint.

Chaque interface de base d’une interface doit être compatibles avec la sortie (sécurité de Variance).Every base interface of an interface must be output-safe (Variance safety). Une classe ou un struct qui implémente une interface également implicitement implémente toutes les interfaces de base de l’interface.A class or struct that implements an interface also implicitly implements all of the interface's base interfaces.

Corps de l’interfaceInterface body

Le interface_body d’une interface définit les membres de l’interface.The interface_body of an interface defines the members of the interface.

interface_body
    : '{' interface_member_declaration* '}'
    ;

Membres de l’interfaceInterface members

Les membres d’une interface sont les membres hérités des interfaces de base et les membres déclarés par l’interface elle-même.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
    ;

Une déclaration d’interface peut déclarer zéro ou plusieurs membres.An interface declaration may declare zero or more members. Les membres d’une interface doivent être des méthodes, propriétés, événements ou indexeurs.The members of an interface must be methods, properties, events, or indexers. Une interface ne peut pas contenir de constantes, champs, opérateurs, constructeurs d’instance, destructeurs ou types, ni une interface peut contenir les membres statiques d’aucune sorte.An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.

Tous les membres d’interface sont implicitement publics.All interface members implicitly have public access. Il s’agit d’une erreur lors de la compilation des déclarations de membre d’interface comprennent des modificateurs.It is a compile-time error for interface member declarations to include any modifiers. En particulier, les membres d’interface ne peuvent pas être déclarés avec les modificateurs abstract, public, protected, internal, private, virtual, override, ou static.In particular, interfaces members cannot be declared with the modifiers abstract, public, protected, internal, private, virtual, override, or static.

L’exempleThe 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; }
}

déclare une interface qui contient l’un des types possibles de membres : Une méthode, une propriété, un événement et un indexeur.declares an interface that contains one each of the possible kinds of members: A method, a property, an event, and an indexer.

Un interface_declaration crée un nouvel espace de déclaration (déclarations) et le interface_member_declarations immédiatement contenus par le interface_declaration introduire de nouveaux membres dans cet espace de déclaration.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. Les règles suivantes s’appliquent aux interface_member_declaration%s :The following rules apply to interface_member_declarations:

  • Le nom d’une méthode doit différer des noms de toutes les propriétés et les événements déclarés dans la même interface.The name of a method must differ from the names of all properties and events declared in the same interface. En outre, la signature (Signatures et surcharge) d’une méthode doit être différente des signatures de toutes les autres méthodes déclarées dans la même interface, et deux méthodes déclarées dans la même interface ne peuvent pas avoir signatures qui diffèrent uniquement par ref et 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 by ref and out.
  • Le nom d’une propriété ou un événement doit différer des noms de tous les autres membres déclarés dans la même interface.The name of a property or event must differ from the names of all other members declared in the same interface.
  • La signature d’un indexeur doit se distinguer de tous les autres indexeurs déclarés dans la même interface.The signature of an indexer must differ from the signatures of all other indexers declared in the same interface.

Les membres hérités d’une interface sont spécifiquement ne fait pas partie de l’espace de déclaration de l’interface.The inherited members of an interface are specifically not part of the declaration space of the interface. Par conséquent, une interface est autorisée à déclarer un membre portant le même nom ou la même signature qu’un membre hérité.Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. Lorsque cela se produit, le membre d’interface dérivée est dite pour masquer le membre de l’interface de base.When this occurs, the derived interface member is said to hide the base interface member. Masquer un membre hérité n'est pas considéré comme une erreur, mais elle entraîne le compilateur à émettre un avertissement.Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. Pour supprimer l’avertissement, la déclaration du membre d’interface dérivée doit inclure un new modificateur pour indiquer que le membre dérivé est conçu pour masquer le membre de base.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. Ce sujet est abordé plus en détail dans masquage par héritage.This topic is discussed further in Hiding through inheritance.

Si un new modificateur est inclus dans une déclaration qui ne masque pas un membre hérité, un avertissement est émis à cet effet.If a new modifier is included in a declaration that doesn't hide an inherited member, a warning is issued to that effect. Cet avertissement est supprimé en supprimant le new modificateur.This warning is suppressed by removing the new modifier.

Notez que les membres de classe object ne sont pas, strictement parlant, les membres de n’importe quelle interface (membres de l’Interface).Note that the members in class object are not, strictly speaking, members of any interface (Interface members). Toutefois, les membres de classe object sont disponibles via la recherche de membres dans n’importe quel type d’interface (recherche de membres).However, the members in class object are available via member lookup in any interface type (Member lookup).

Méthodes d’interfaceInterface methods

Méthodes d’interface sont déclarés à l’aide de interface_method_declaration%s :Interface 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* ';'
    ;

Le attributs, return_type, identificateur, et formal_parameter_list d’une déclaration de méthode d’interface ont la même ce qui signifie que ceux d’une déclaration de méthode dans une classe (méthodes).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). Une déclaration de méthode d’interface n’est pas autorisée à spécifier un corps de méthode et la déclaration par conséquent se termine toujours par un point-virgule.An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon.

Chaque type de paramètre formel d’une méthode d’interface doit être entrée-safe (sécurité de Variance), et le type de retour doit être void ou compatibles avec la sortie.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. En outre, chaque contrainte de type classe, la contrainte de type interface et la contrainte de paramètre de type sur n’importe quel paramètre de type de la méthode doivent être entrée-safe.Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method must be input-safe.

Ces règles garantissent que tout covariant ou contravariant d’utilisation de l’interface reste type sécurisé.These rules ensure that any covariant or contravariant usage of the interface remains type-safe. Par exemple :For example,

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

n’est pas conforme, car l’utilisation de T comme une contrainte de paramètre de type sur U n’est pas entrée-safe.is illegal because the usage of T as a type parameter constraint on U is not input-safe.

Cette restriction n’étaient pas en place il serait possible d’enfreindre la sécurité de type de la manière suivante :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>();

Il s’agit en fait un appel à C.M<E>.This is actually a call to C.M<E>. Mais cet appel nécessite que E dérivent D, de sorte que la sécurité de type sera enfreinte ici.But that call requires that E derive from D, so type safety would be violated here.

Propriétés de l'interfaceInterface properties

Propriétés d’interface sont déclarées à l’aide de interface_property_declaration%s :Interface 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' ';'
    ;

Le attributs, type, et identificateur d’une déclaration de propriété d’interface ont la même signification que ceux d’une déclaration de propriété dans une classe ( Propriétés).The attributes, type, and identifier of an interface property declaration have the same meaning as those of a property declaration in a class (Properties).

Les accesseurs d’une déclaration de propriété d’interface correspondent aux accesseurs d’une déclaration de propriété de classe (accesseurs), sauf que le corps de l’accesseur doit toujours être un point-virgule.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. Par conséquent, les accesseurs indiquent simplement si la propriété est en lecture-écriture, en lecture seule ou en écriture seule.Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.

Le type d’une propriété d’interface doit être sécurisé de sortie s’il existe un accesseur get et doit être entrée-safe s’il existe un accesseur 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.

Événements d’interfaceInterface events

Événements d’interface sont déclarés à l’aide de interface_event_declaration%s :Interface events are declared using interface_event_declarations:

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

Le attributs, type, et identificateur d’une déclaration event d’interface ont la même signification que ceux d’une déclaration d’événement dans une classe (événements ).The attributes, type, and identifier of an interface event declaration have the same meaning as those of an event declaration in a class (Events).

Le type d’un événement d’interface doit être entrée-safe.The type of an interface event must be input-safe.

Indexeurs d’interfaceInterface indexers

Indexeurs d’interface sont déclarés à l’aide de interface_indexer_declaration%s :Interface indexers are declared using interface_indexer_declarations:

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

Le attributs, type, et formal_parameter_list d’une déclaration d’indexeur interface ont la même signification que ceux d’une déclaration d’indexeur dans une classe ( Indexeurs).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).

Les accesseurs d’une déclaration d’indexeur interface correspondent aux accesseurs d’une déclaration d’indexeur de classe (indexeurs), sauf que le corps de l’accesseur doit toujours être un point-virgule.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. Par conséquent, les accesseurs indiquent simplement si l’indexeur est en lecture-écriture, en lecture seule ou en écriture seule.Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.

Tous les types de paramètres formels d’un indexeur d’interface doivent être entrée-safe.All the formal parameter types of an interface indexer must be input-safe . En outre, n’importe quel out ou ref les types de paramètre formel doivent également être compatibles avec la sortie.In addition, any out or ref formal parameter types must also be output-safe. Notez que même out paramètres sont requis pour être sécurisé à l’entrée, en raison d’une limitation de la plateforme sous-jacente de l’exécution.Note that even out parameters are required to be input-safe, due to a limitation of the underlying execution platform.

Le type d’un indexeur d’interface doit être sécurisé de sortie s’il existe un accesseur get et doit être entrée-safe s’il existe un accesseur 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.

Accès aux membres d’interfaceInterface member access

Membres d’interface sont accessibles via l’accès au membre (l’accès au membre) et accès d’indexeur (accès indexeur) expressions de la forme I.M et I[A], où I est un type interface, M est une méthode, une propriété ou un événement de ce type d’interface, et A est une liste d’arguments indexeur.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.

Pour les interfaces qui sont strictement à héritage unique (chaque interface dans la chaîne d’héritage possède exactement zéro ou une interface de base directe), les effets de la recherche de membres (recherche de membres), appel de méthode ( Appels de méthode) et accès d’indexeur (accès indexeur) règles sont exactement les mêmes que pour les classes et structs : Plus dérivés masquer des membres moins dérivée de membres avec le même nom ou la signature.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. Toutefois, pour les interfaces de l’héritage multiple, ambiguïtés peuvent se produire lorsque deux ou plus des interfaces de base non liées déclarent des membres avec le même nom ou la même signature.However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. Cette section montre plusieurs exemples de telles situations.This section shows several examples of such situations. Dans tous les cas, des casts explicites peuvent être utilisés pour résoudre les ambiguïtés.In all cases, explicit casts can be used to resolve the ambiguities.

Dans l’exempleIn 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
    }
}

les deux premières instructions provoquent des erreurs de compilation, car la recherche de membres (recherche de membres) de Count dans IListCounter est ambigu.the first two statements cause compile-time errors because the member lookup (Member lookup) of Count in IListCounter is ambiguous. Comme l’illustre l’exemple, l’ambiguïté est résolue en effectuant un cast x au type d’interface de base appropriée.As illustrated by the example, the ambiguity is resolved by casting x to the appropriate base interface type. De telles conversions n’ont aucun coût d’exécution, il s’agit simplement d’affichage de l’instance comme un type moins dérivé au moment de la compilation.Such casts have no run-time costs—they merely consist of viewing the instance as a less derived type at compile-time.

Dans l’exempleIn 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
    }
}

l’appel n.Add(1) sélectionne IInteger.Add en appliquant les règles de résolution de surcharge de la résolution de surcharge.the invocation n.Add(1) selects IInteger.Add by applying the overload resolution rules of Overload resolution. De même, l’appel n.Add(1.0) sélectionne IDouble.Add.Similarly the invocation n.Add(1.0) selects IDouble.Add. Lorsque des casts explicites sont insérés, il y a des candidate qu’une seule méthode et donc pas d’ambiguïté.When explicit casts are inserted, there is only one candidate method, and thus no ambiguity.

Dans l’exempleIn 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
    }
}

le IBase.F membre est masqué par le ILeft.F membre.the IBase.F member is hidden by the ILeft.F member. L’appel d.F(1) sélectionne le ILeft.F, même si IBase.F semble ne pas être masqué dans le chemin d’accès qui mène à 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.

La règle intuitive de masquage des interfaces à héritage multiple est simple : Si un membre est masqué dans n’importe quel chemin d’accès, il est masqué dans tous les chemins d’accès.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. Étant donné que le chemin d’accès à partir de IDerived à ILeft à IBase masque IBase.F, le membre est également masqué dans le chemin d’accès à partir de 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.

Noms de membre d’interface qualifié completFully qualified interface member names

Un membre d’interface est parfois désigné par son nom qualifié complet.An interface member is sometimes referred to by its fully qualified name. Le nom qualifié complet d’un membre d’interface se compose du nom de l’interface dans laquelle le membre est déclaré par un point, suivi par le nom du membre.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. Le nom qualifié complet d’un membre fait référence à l’interface dans laquelle le membre est déclaré.The fully qualified name of a member references the interface in which the member is declared. Par exemple, compte tenu des déclarationsFor example, given the declarations

interface IControl
{
    void Paint();
}

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

le nom qualifié complet de Paint est IControl.Paint et le nom qualifié complet de SetText est ITextBox.SetText.the fully qualified name of Paint is IControl.Paint and the fully qualified name of SetText is ITextBox.SetText.

Dans l’exemple ci-dessus, il n’est pas possible de faire référence à Paint comme ITextBox.Paint.In the example above, it is not possible to refer to Paint as ITextBox.Paint.

Lorsqu’une interface fait partie d’un espace de noms, le nom qualifié complet d’un membre d’interface inclut le nom de l’espace de noms.When an interface is part of a namespace, the fully qualified name of an interface member includes the namespace name. Exemple :For example

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

Ici, le nom qualifié complet de le Clone méthode est System.ICloneable.Clone.Here, the fully qualified name of the Clone method is System.ICloneable.Clone.

Implémentations d'interfacesInterface implementations

Interfaces peuvent être implémentées par les classes et structs.Interfaces may be implemented by classes and structs. Pour indiquer qu’une classe ou un struct implémente directement une interface, l’identificateur d’interface est inclus dans la liste de classe de base de la classe ou structure.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. Exemple :For example:

interface ICloneable
{
    object Clone();
}

interface IComparable
{
    int CompareTo(object other);
}

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

Une classe ou un struct qui implémente directement une interface également directement implémente toutes les interfaces de base de l’interface implicitement.A class or struct that directly implements an interface also directly implements all of the interface's base interfaces implicitly. Cela est vrai même si la classe ou structure ne répertorie pas explicitement toutes les interfaces de base dans la liste de classe de base.This is true even if the class or struct doesn't explicitly list all base interfaces in the base class list. Exemple :For example:

interface IControl
{
    void Paint();
}

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

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

Ici, la classe TextBox implémente à la fois IControl et ITextBox.Here, class TextBox implements both IControl and ITextBox.

Lorsqu’une classe C directement implémente une interface, toutes les classes dérivées de C également implémente l’interface implicitement.When a class C directly implements an interface, all classes derived from C also implement the interface implicitly. Les interfaces de base spécifiés dans une déclaration de classe peuvent être des types d’interface construite (types construits).The base interfaces specified in a class declaration can be constructed interface types (Constructed types). Une interface de base ne peut pas être un paramètre de type sur son propre, même si elle peut impliquer les paramètres de type qui sont dans la portée.A base interface cannot be a type parameter on its own, though it can involve the type parameters that are in scope. Le code suivant illustre comment une classe peut implémenter et étendre des types construits :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> {}

Les interfaces de base d’une déclaration de classe générique doivent respecter la règle de l’unicité décrite dans l’unicité des interfaces implémentées.The base interfaces of a generic class declaration must satisfy the uniqueness rule described in Uniqueness of implemented interfaces.

Implémentations de membres d’interface expliciteExplicit interface member implementations

Dans le cadre de l’implémentation des interfaces, une classe ou un struct peut déclarer implémentations de membres d’interface explicite.For purposes of implementing interfaces, a class or struct may declare explicit interface member implementations. Une implémentation de membre d’interface explicite est une déclaration de méthode, propriété, événement ou l’indexeur qui fait référence à un nom de membre d’interface qualifié complet.An explicit interface member implementation is a method, property, event, or indexer declaration that references a fully qualified interface member name. Exemple :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) {...}
}

Ici IDictionary<int,T>.this et IDictionary<int,T>.Add est des implémentations de membres d’interface explicite.Here IDictionary<int,T>.this and IDictionary<int,T>.Add are explicit interface member implementations.

Dans certains cas, le nom d’un membre d’interface n’est peut-être pas approprié pour la classe d’implémentation, dans lequel cas le membre d’interface peut être implémentée à l’aide d’implémentation de membre d’interface explicite.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. Implémente une classe qui implémente une abstraction de fichier, par exemple, probablement un Close fonction membre qui a pour effet de libérer la ressource de fichier et implémenter le Dispose méthode de la IDisposable interface à l’aide d’interface explicite implémentation de membre :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);
    }
}

Il n’est pas possible d’accéder à une implémentation de membre d’interface explicite via son nom qualifié complet dans un appel de méthode, propriété ou accès indexeur.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. Une implémentation de membre d’interface explicite est uniquement accessible via une instance d’interface et est référencée dans ce cas simplement par son nom de membre.An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.

Il s’agit d’une erreur de compilation pour une implémentation de membre d’interface explicite inclure des modificateurs d’accès, et c’est une erreur de compilation pour inclure les modificateurs abstract, virtual, override, ou 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.

Implémentations de membres d’interface explicites ont des caractéristiques d’une accessibilité différente que d’autres membres.Explicit interface member implementations have different accessibility characteristics than other members. Étant donné que les implémentations de membres d’interface explicites ne sont jamais accessibles par leur nom qualifié complet dans un appel de méthode ou d’un accès à la propriété, elles se trouvent dans un sens privé.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. Toutefois, dans la mesure où ils sont accessibles via une instance d’interface, ils sont dans un sens également public.However, since they can be accessed through an interface instance, they are in a sense also public.

Implémentations de membres d’interface explicites ont pour objectif principal :Explicit interface member implementations serve two primary purposes:

  • Étant donné que les implémentations de membres d’interface explicites ne sont pas accessibles via des instances de classe ou un struct, ils permettent d’implémentations d’interface à exclure de l’interface publique d’une classe ou un struct.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. Cela est particulièrement utile lorsqu’une classe ou struct implémente une interface interne qui ne présente aucun intérêt pour le consommateur de cette classe ou 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.
  • Implémentations de membres d’interface explicites permettent de lever l’ambiguïté de membres d’interface avec la même signature.Explicit interface member implementations allow disambiguation of interface members with the same signature. Sans les implémentations de membres d’interface explicite il serait impossible pour une classe ou un struct d’avoir différentes implémentations de membres avec la même signature de l’interface et le type de retour, comme il serait impossible pour une classe ou un struct d’avoir une implémentation tous les membres d’interface avec la même signature, mais avec différents types de retournés.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.

Pour une implémentation de membre d’interface explicite soit valide, la classe ou structure doit nommer une interface dans sa liste de classe de base qui contient un membre dont le nom qualifié complet, type et les types de paramètres correspondent exactement à ceux du membre d’interface explicite mise en œuvre.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. Par conséquent, dans la classe suivanteThus, in the following class

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

la déclaration de IComparable.CompareTo génère une erreur de compilation, car IComparable n’est pas répertorié dans la liste de classe de base de Shape et n’est pas une interface de base de 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. De même, dans les déclarationsLikewise, in the declarations

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

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

la déclaration de ICloneable.Clone dans Ellipse génère une erreur de compilation, car ICloneable n’est pas explicitement répertorié dans la liste de classe de base de 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.

Le nom qualifié complet d’un membre d’interface doit faire référence à l’interface dans laquelle le membre a été déclaré.The fully qualified name of an interface member must reference the interface in which the member was declared. Par conséquent, dans les déclarationsThus, 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) {...}
}

l’implémentation de membre d’interface explicite de Paint doit être écrit en tant que IControl.Paint.the explicit interface member implementation of Paint must be written as IControl.Paint.

Unicité des interfaces implémentéesUniqueness of implemented interfaces

Les interfaces implémentées par une déclaration de type générique doivent rester uniques pour tous les types construits possible.The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. Sans cette règle, il serait impossible de déterminer la méthode à appeler pour certains types construits.Without this rule, it would be impossible to determine the correct method to call for certain constructed types. Par exemple, une déclaration de classe générique ont été autorisés à être écrit comme suit :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() {...}
}

Ont été cela autorisé, il serait impossible de déterminer le code à exécuter dans le cas suivant :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();

Pour déterminer si la liste de l’interface d’une déclaration de type générique est valide, les étapes suivantes sont effectuées :To determine if the interface list of a generic type declaration is valid, the following steps are performed:

  • Laisser L la liste des interfaces spécifiées directement dans une classe générique, un struct ou une déclaration d’interface C.Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
  • Ajouter à L les interfaces des interfaces déjà de base L.Add to L any base interfaces of the interfaces already in L.
  • Supprimer les doublons de L.Remove any duplicates from L.
  • Si tout construit type créé à partir de C serait, une fois que les arguments de type sont substitués dans L, provoquer deux interfaces dans L sont identiques, puis la déclaration de C n’est pas valide.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. Déclarations de contrainte ne sont pas considérées lors de la détermination de tous les types construits possible.Constraint declarations are not considered when determining all possible constructed types.

Dans la déclaration de classe X ci-dessus, la liste des interfaces L se compose de I<U> et I<V>.In the class declaration X above, the interface list L consists of I<U> and I<V>. La déclaration n’est pas valide, car un type avec construit U et V en cours du même type entraînerait ces deux interfaces comme des types identiques.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.

Il est possible pour les interfaces spécifiées aux niveaux d’héritage différents pour unifier :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() {...}
}

Ce code est valid, même si Derived<U,V> implémente à la fois I<U> et I<V>.This code is valid even though Derived<U,V> implements both I<U> and I<V>. Le codeThe code

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

appelle la méthode dans Derived, étant donné que Derived<int,int> efficacement ré-implémente I<int> (réimplémenter l’Interface).invokes the method in Derived, since Derived<int,int> effectively re-implements I<int> (Interface re-implementation).

Implémentation des méthodes génériquesImplementation of generic methods

Lorsqu’une méthode générique implicitement implémente une méthode d’interface, les contraintes données chaque paramètre de type de méthode doit être équivalente dans les deux déclarations (après n’importe quel type d’interface paramètres sont remplacés par les arguments de type approprié), où (méthode) paramètres de type sont identifiées par les positions ordinales, de gauche à droite.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.

Lorsqu’une méthode générique implémente explicitement une méthode d’interface, toutefois, aucune contrainte n’est autorisées sur la méthode d’implémentation.When a generic method explicitly implements an interface method, however, no constraints are allowed on the implementing method. Au lieu de cela, les contraintes sont héritées de la méthode d’interfaceInstead, 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
}

La méthode C.F<T> implémente implicitement les I<object,C,string>.F<T>.The method C.F<T> implicitly implements I<object,C,string>.F<T>. Dans ce cas, C.F<T> n’est pas nécessaire (ni autorisés) pour spécifier la contrainte T:object dans la mesure où object est une contrainte implicite sur tous les paramètres de type.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. La méthode C.G<T> implémente implicitement I<object,C,string>.G<T> , car les contraintes correspondent à celles dans l’interface, une fois que les paramètres de type d’interface sont remplacés par les arguments de type correspondant.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. La contrainte pour la méthode C.H<T> est une erreur, car les types sealed (string dans ce cas) ne peut pas être utilisé en tant que contraintes.The constraint for method C.H<T> is an error because sealed types (string in this case) cannot be used as constraints. L’omission de la contrainte également serait une erreur, car les contraintes d’implémentations de méthode d’interface implicite sont requises pour faire correspondre.Omitting the constraint would also be an error since constraints of implicit interface method implementations are required to match. Par conséquent, il est impossible d’implémenter implicitement I<object,C,string>.H<T>.Thus, it is impossible to implicitly implement I<object,C,string>.H<T>. Cette méthode d’interface peut uniquement être implémentée à l’aide d’une implémentation de membre d’interface explicite :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);
    }
}

Dans cet exemple, l’implémentation de membre d’interface explicite appelle une méthode publique avec des contraintes strictement plus faibles.In this example, the explicit interface member implementation invokes a public method having strictly weaker constraints. Notez que l’affectation de t à s est valide depuis T hérite d’une contrainte de T:string, même si cette contrainte n’est pas pouvant être exprimée dans le code source.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.

Mappage d’interfaceInterface mapping

Une classe ou un struct doit fournir des implémentations de tous les membres des interfaces qui sont répertoriées dans la liste de classe de base de la classe ou structure.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. Le processus de localisation des implémentations de membres d’interface dans une classe ou struct d’implémentation est appelé mappage d’interface.The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.

Mappage d’interface pour une classe ou un struct C recherche une implémentation pour chaque membre de chaque interface spécifiée dans la liste de classe de base de 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. L’implémentation d’un membre d’interface particulier I.M, où I est l’interface dans laquelle le membre M est déclaré, est déterminée en examinant chaque classe ou struct S, en commençant par C et répétition pour chaque classe de base consécutive de C, jusqu'à ce qu’il trouve une correspondance :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:

  • Si S contient une déclaration d’une implémentation de membre d’interface explicite qui correspond à I et M, ce membre est l’implémentation de 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.
  • Sinon, si S contient une déclaration d’un membre public non statique qui correspond à M, ce membre est l’implémentation de 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. Si plusieurs correspondances d’un seul membre, il n’est pas spécifié le membre qui est l’implémentation de I.M.If more than one member matches, it is unspecified which member is the implementation of I.M. Cette situation peut se produire uniquement si S est un type construit, où les deux membres tel que déclaré dans le type générique ont des signatures différentes, mais les arguments de type que leurs signatures identique.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.

Une erreur de compilation se produit si les implémentations ne peut pas être localisées pour tous les membres de toutes les interfaces spécifiées dans la liste de classe de base de 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. Notez que les membres d’une interface incluent les membres qui sont héritées d’interfaces de base.Note that the members of an interface include those members that are inherited from base interfaces.

À des fins de mappage d’interface, un membre de classe A correspond à un membre d’interface B lorsque :For purposes of interface mapping, a class member A matches an interface member B when:

  • A et B sont des méthodes et le nom, le type, et les listes de paramètres formels de A et B sont identiques.A and B are methods, and the name, type, and formal parameter lists of A and B are identical.
  • A et B sont des propriétés, le nom et le type de A et B sont identiques, et A a les mêmes accesseurs que B (A est autorisé à avoir des accesseurs supplémentaires s’il n’est pas une interface explicite implémentation de membre).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 et B sont des événements et le nom et le type de A et B sont identiques.A and B are events, and the name and type of A and B are identical.
  • A et B sont des indexeurs, le type et les listes de paramètres formels de A et B sont identiques, et A a les mêmes accesseurs que B (A est autorisé à avoir des accesseurs supplémentaires s’il n’est pas un implémentation de membre d’interface explicite).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).

Les implications notables de l’algorithme de mappage d’interface sont :Notable implications of the interface mapping algorithm are:

  • Implémentations de membres d’interface explicites sont prioritaires sur les autres membres dans la même classe ou struct lors de la détermination du membre de classe ou struct qui implémente un membre d’interface.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.
  • Les membres non publics ni statiques participent au mappage d’interface.Neither non-public nor static members participate in interface mapping.

Dans l’exempleIn the example

interface ICloneable
{
    object Clone();
}

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

le ICloneable.Clone membre C devient l’implémentation de Clone dans ICloneable , car les implémentations de membres d’interface explicites sont prioritaires sur les autres membres.the ICloneable.Clone member of C becomes the implementation of Clone in ICloneable because explicit interface member implementations take precedence over other members.

Si une classe ou un struct implémente deux ou plusieurs interfaces contenant un membre avec le même nom, type et les types de paramètre, il est possible de mapper chacun de ces membres d’interface à un seul membre de classe ou un struct.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. Exemple :For example

interface IControl
{
    void Paint();
}

interface IForm
{
    void Paint();
}

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

Ici, le Paint méthodes des deux IControl et IForm sont mappées sur le Paint méthode dans Page.Here, the Paint methods of both IControl and IForm are mapped onto the Paint method in Page. Il est bien sûr également possible d’avoir des implémentations de membres d’interface explicite distincte pour les deux méthodes.It is of course also possible to have separate explicit interface member implementations for the two methods.

Si une classe ou un struct implémente une interface qui contient les membres masqués, certains membres doivent nécessairement être implémentés via des implémentations de membres d’interface explicite.If a class or struct implements an interface that contains hidden members, then some members must necessarily be implemented through explicit interface member implementations. Exemple :For example

interface IBase
{
    int P { get; }
}

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

Une implémentation de cette interface nécessite au moins une implémentation de membre d’interface explicite et prendrait l’une des formes suivantesAn 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() {...}
}

Lorsqu’une classe implémente plusieurs interfaces qui ont la même interface de base, il peut y avoir qu’une seule implémentation de l’interface de base.When a class implements multiple interfaces that have the same base interface, there can be only one implementation of the base interface. Dans l’exempleIn 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) {...}
}

Il n’est pas possible d’avoir des implémentations distinctes pour le IControl nommé dans la liste de classe de base, le IControl héritée par ITextBoxet le IControl héritée par 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. En effet, il n’existe aucune notion d’identité séparée pour ces interfaces.Indeed, there is no notion of a separate identity for these interfaces. Au lieu de cela, les implémentations de ITextBox et IListBox partagent la même implémentation de IControl, et ComboBox est considéré comme il vous suffit d’implémenter trois interfaces, IControl, ITextBox, et 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.

Les membres de classe de base participent au mappage d’interface.The members of a base class participate in interface mapping. Dans l’exempleIn the example

interface Interface1
{
    void F();
}

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

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

la méthode F dans Class1 est utilisée dans Class2d’implémentation de Interface1.the method F in Class1 is used in Class2's implementation of Interface1.

Héritage de l’implémentation d’interfaceInterface implementation inheritance

Une classe hérite de toutes les implémentations d’interface fournies par ses classes de base.A class inherits all interface implementations provided by its base classes.

Sans explicitement ré-implémenter une interface, une classe dérivée ne peut en aucun cas modifier les mappages d’interface hérite de ses classes de base.Without explicitly re-implementing an interface, a derived class cannot in any way alter the interface mappings it inherits from its base classes. Par exemple, dans les déclarationsFor example, in the declarations

interface IControl
{
    void Paint();
}

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

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

le Paint méthode dans TextBox masque la Paint méthode dans Control, mais il ne modifie pas le mappage de Control.Paint sur IControl.Paintet les appels à Paint via la classe seront instances et les instances de l’interface avoir les effets suivantsthe 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();

Toutefois, lorsqu’une méthode d’interface est mappée à une méthode virtuelle dans une classe, il est possible pour les classes dérivées de substituer la méthode virtuelle et de modifier l’implémentation de l’interface.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. Par exemple, les déclarations ci-dessus de réécritureFor example, rewriting the declarations above to

interface IControl
{
    void Paint();
}

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

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

les effets suivants seront maintenant appliquésthe 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();

Dans la mesure où les implémentations de membres d’interface explicite ne peut pas être déclarées comme virtuelles, il n’est pas possible de remplacer une implémentation de membre d’interface explicite.Since explicit interface member implementations cannot be declared virtual, it is not possible to override an explicit interface member implementation. Toutefois, il est parfaitement valide pour une implémentation de membre d’interface explicite appeler une autre méthode, et que les autres méthode peut être déclarée virtuel pour autoriser les classes dérivées pour la remplacer.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. Exemple :For example

interface IControl
{
    void Paint();
}

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

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

Ici, les classes dérivées de Control pouvez le spécialiser l’implémentation de IControl.Paint en substituant le PaintControl (méthode).Here, classes derived from Control can specialize the implementation of IControl.Paint by overriding the PaintControl method.

Réimplémentation de l’interfaceInterface re-implementation

Une classe qui hérite d’une implémentation d’interface est autorisée à ré-implémenter l’interface en l’incluant dans la liste de classe de base.A class that inherits an interface implementation is permitted to re-implement the interface by including it in the base class list.

Une nouvelle implémentation d’une interface suit exactement les règles de mappage interface même que l’implémentation initiale d’une interface.A re-implementation of an interface follows exactly the same interface mapping rules as an initial implementation of an interface. Par conséquent, le mappage d’interface hérité n’a aucun effet sur le mappage d’interface établie pour la nouvelle implémentation de l’interface.Thus, the inherited interface mapping has no effect whatsoever on the interface mapping established for the re-implementation of the interface. Par exemple, dans les déclarationsFor example, in the declarations

interface IControl
{
    void Paint();
}

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

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

le fait que Control mappe IControl.Paint sur Control.IControl.Paint n’affecte pas la réimplémentation dans MyControl, laquelle correspond IControl.Paint sur 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.

Hérité des déclarations de membre public et membre d’interface explicite hérité déclarations participent dans le processus de mappage d’interface pour les interfaces implémentées de nouveau.Inherited public member declarations and inherited explicit interface member declarations participate in the interface mapping process for re-implemented interfaces. Exemple :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() {}
}

Ici, l’implémentation de IMethods dans Derived mappe les méthodes d’interface sur Derived.F, Base.IMethods.G, Derived.IMethods.H, et 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.

Lorsqu’une classe implémente une interface, il implicitement toutes les interfaces de base de cette interface implémente également.When a class implements an interface, it implicitly also implements all of that interface's base interfaces. De même, une nouvelle implémentation d’une interface est également implicitement une réimplémentation de toutes les interfaces de base de l’interface.Likewise, a re-implementation of an interface is also implicitly a re-implementation of all of the interface's base interfaces. Exemple :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() {...}
}

Ici, la réimplémentation de IDerived nouveau implémente également IBase, le mappage IBase.F sur D.F.Here, the re-implementation of IDerived also re-implements IBase, mapping IBase.F onto D.F.

Interfaces et classes abstraitesAbstract classes and interfaces

Comme une classe non abstraite, une classe abstraite doit fournir des implémentations de tous les membres des interfaces qui sont répertoriées dans la liste de classe de base de la classe.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. Toutefois, une classe abstraite est autorisée à mapper les méthodes d’interface à des méthodes abstraites.However, an abstract class is permitted to map interface methods onto abstract methods. Exemple :For example

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

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

Ici, l’implémentation de IMethods mappe F et G à des méthodes abstraites, qui doit être substitué dans les classes non abstraites dérivées de 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.

Notez que les implémentations de membres d’interface explicite ne peut pas être abstraites, mais implémentations de membres d’interface explicites sont bien entendu autorisées à appeler les méthodes abstraites.Note that explicit interface member implementations cannot be abstract, but explicit interface member implementations are of course permitted to call abstract methods. Exemple :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();
}

Ici, les classes non abstraites dérivées de C serait nécessaire pour remplacer FF et GG, et offrir ainsi l’implémentation réelle de IMethods.Here, non-abstract classes that derive from C would be required to override FF and GG, thus providing the actual implementation of IMethods.