InterfacesInterfaces

Uma interface define um contrato.An interface defines a contract. Uma classe ou struct que implementa uma interface deve aderir a seu contrato.A class or struct that implements an interface must adhere to its contract. Uma interface pode herdar de várias interfaces base e uma classe ou estrutura pode implementar várias interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.

As interfaces podem conter métodos, propriedades, eventos e indexadores.Interfaces can contain methods, properties, events, and indexers. A própria interface não fornece implementações para os membros que ele define.The interface itself does not provide implementations for the members that it defines. A interface simplesmente especifica os membros que devem ser fornecidos por classes ou estruturas que implementam a interface.The interface merely specifies the members that must be supplied by classes or structs that implement the interface.

Declarações de interfaceInterface declarations

Uma interface_declaration é uma type_declaration (declarações de tipo) que declara um novo tipo de 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 ';'?
    ;

Um interface_declaration consiste em um conjunto opcional de atributos (atributos), seguido por um conjunto opcional de interface_modifier s (modificadores de interface), seguido por um partial modificador opcional, seguido pela palavra-chave interface e um identificador que nomeia a interface, seguido por uma especificação opcional de variant_type_parameter_list (listas de parâmetros de tipo Variant), seguido por uma especificação opcional de Interface_base (interfaces base), seguida por uma especificação opcional de type_parameter_constraints_clause s (restrições de parâmetro de tipo), seguido por um interface_body (corpo da interface), opcionalmente seguido por um pontoAn interface_declaration consists of an optional set of attributes (Attributes), followed by an optional set of interface_modifier s (Interface modifiers), followed by an optional partial modifier, followed by the keyword interface and an identifier that names the interface, followed by an optional variant_type_parameter_list specification (Variant type parameter lists), followed by an optional interface_base specification (Base interfaces), followed by an optional type_parameter_constraints_clause s specification (Type parameter constraints), followed by an interface_body (Interface body), optionally followed by a semicolon.

Modificadores de interfaceInterface modifiers

Um interface_declaration pode, opcionalmente, incluir uma sequência de modificadores de interface:An interface_declaration may optionally include a sequence of interface modifiers:

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

É um erro de tempo de compilação para o mesmo modificador aparecer várias vezes em uma declaração de interface.It is a compile-time error for the same modifier to appear multiple times in an interface declaration.

O new modificador é permitido somente em interfaces definidas dentro de uma classe.The new modifier is only permitted on interfaces defined within a class. Ele especifica que a interface oculta um membro herdado com o mesmo nome, conforme descrito no novo modificador.It specifies that the interface hides an inherited member by the same name, as described in The new modifier.

Os public protected internal modificadores,, e private controlam a acessibilidade da interface.The public, protected, internal, and private modifiers control the accessibility of the interface. Dependendo do contexto no qual a declaração de interface ocorre, somente alguns desses modificadores podem ser permitidos (acessibilidade declarada).Depending on the context in which the interface declaration occurs, only some of these modifiers may be permitted (Declared accessibility).

Modificador parcialPartial modifier

O partial modificador indica que esse interface_declaration é uma declaração de tipo parcial.The partial modifier indicates that this interface_declaration is a partial type declaration. Várias declarações de interface parciais com o mesmo nome dentro de um namespace delimitador ou declaração de tipo são combinadas para formar uma declaração de interface, seguindo as regras especificadas em tipos parciais.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.

Listas de parâmetros de tipo VariantVariant type parameter lists

Listas de parâmetros de tipo Variant só podem ocorrer em tipos de interface e delegados.Variant type parameter lists can only occur on interface and delegate types. A diferença entre as type_parameter_list comuns é a variance_annotation opcional em cada parâmetro de tipo.The difference from ordinary type_parameter_list s is the optional variance_annotation on each type parameter.

variant_type_parameter_list
    : '<' variant_type_parameters '>'
    ;

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

variance_annotation
    : 'in'
    | 'out'
    ;

Se a anotação de variação for out , o parâmetro de tipo é considerado *covariable _.If the variance annotation is out, the type parameter is said to be *covariant _. Se a anotação de variação for in , o parâmetro de tipo será considerado contravariant.If the variance annotation is in, the type parameter is said to be contravariant. Se não houver nenhuma anotação de variação, o parâmetro de tipo será considerado _ invariável *.If there is no variance annotation, the type parameter is said to be _*invariant**.

No exemploIn the example

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

X é covariant, Y é contravariant e Z é invariável.X is covariant, Y is contravariant and Z is invariant.

Segurança de variaçãoVariance safety

A ocorrência de anotações de variação na lista de parâmetros de tipo de um tipo restringe os locais em que os tipos podem ocorrer dentro da declaração de tipo.The occurrence of variance annotations in the type parameter list of a type restricts the places where types can occur within the type declaration.

Um tipo T é de saída-não seguro se uma das seguintes isenções:A type T is output-unsafe if one of the following holds:

  • T é um parâmetro de tipo contravariantT is a contravariant type parameter
  • T é um tipo de matriz com um tipo de elemento de saída não seguroT is an array type with an output-unsafe element type
  • T é uma interface ou tipo delegado S<A1,...,Ak> construído a partir de um tipo genérico S<X1,...,Xk> , em que pelo menos uma Ai das seguintes isenções: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 é covariant ou invariável e Ai é de saída-não segura.Xi is covariant or invariant and Ai is output-unsafe.
    • Xi é contravariant ou invariável e Ai é de entrada segura.Xi is contravariant or invariant and Ai is input-safe.

Um tipo T é de entrada-não seguro se uma das seguintes isenções:A type T is input-unsafe if one of the following holds:

  • T é um parâmetro de tipo covariantT is a covariant type parameter
  • T é um tipo de matriz com um tipo de elemento de entrada não seguroT is an array type with an input-unsafe element type
  • T é uma interface ou tipo delegado S<A1,...,Ak> construído a partir de um tipo genérico S<X1,...,Xk> , em que pelo menos uma Ai das seguintes isenções: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 é covariant ou invariável e Ai é de entrada-não segura.Xi is covariant or invariant and Ai is input-unsafe.
    • Xi é contravariant ou invariável e Ai é de saída-não segura.Xi is contravariant or invariant and Ai is output-unsafe.

Intuitivamente, um tipo de saída não segura é proibido em uma posição de saída e um tipo de entrada não segura é proibido em uma posição de entrada.Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position.

Um tipo é saída-seguro _ se não for de saída-não seguro e _ de entrada-seguro se não for de entrada-não segura.A type is output-safe _ if it is not output-unsafe, and _ input-safe if it is not input-unsafe.

Conversão de variânciaVariance conversion

A finalidade das anotações de variação é fornecer conversões de brandas (mas ainda de tipo seguro) aos tipos de interface e delegado.The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. Para esse fim, as definições de conversões implícitas (conversões implícitas) e explícitas (conversões explícitas) fazem uso da noção de variância-convertibilidade, que é definida da seguinte maneira: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:

Um tipo T<A1,...,An> é conversível de variação em um tipo T<B1,...,Bn> se T for uma interface ou um tipo delegado declarado com os parâmetros de tipo Variant T<X1,...,Xn> e para cada parâmetro de tipo Variant, Xi uma das seguintes isenções: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 é covariant e uma referência implícita ou conversão de identidade existe de Ai para BiXi is covariant and an implicit reference or identity conversion exists from Ai to Bi
  • Xi é contravariant e uma referência implícita ou conversão de identidade existe em Bi para AiXi is contravariant and an implicit reference or identity conversion exists from Bi to Ai
  • Xi é invariável e existe uma conversão de identidade de Ai para BiXi is invariant and an identity conversion exists from Ai to Bi

Interfaces baseBase interfaces

Uma interface pode herdar de zero ou mais tipos de interface, que são chamados de interfaces base explícitas da interface.An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. Quando uma interface tem uma ou mais interfaces base explícitas, na declaração dessa interface, o identificador de interface é seguido por dois-pontos e uma lista separada por vírgulas de tipos de interface 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
    ;

Para um tipo de interface construída, as interfaces base explícitas são formadas por meio das declarações de interface base explícitas na declaração de tipo genérico e a substituição, para cada type_parameter na declaração de interface base, a type_argument correspondente do tipo construído.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.

As interfaces base explícitas de uma interface devem ser pelo menos tão acessíveis quanto a própria interface (restrições de acessibilidade).The explicit base interfaces of an interface must be at least as accessible as the interface itself (Accessibility constraints). Por exemplo, é um erro de tempo de compilação para especificar uma private internal interface ou no interface_base de uma 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.

É um erro de tempo de compilação para uma interface herdar direta ou indiretamente de si mesma.It is a compile-time error for an interface to directly or indirectly inherit from itself.

As interfaces base de uma interface são as interfaces base explícitas e suas interfaces base.The base interfaces of an interface are the explicit base interfaces and their base interfaces. Em outras palavras, o conjunto de interfaces base é o fechamento transitivo completo das interfaces base explícitas, suas interfaces base explícitas e assim por diante.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. Uma interface herda todos os membros de suas interfaces base.An interface inherits all members of its base interfaces. No exemploIn the example

interface IControl
{
    void Paint();
}

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

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

interface IComboBox: ITextBox, IListBox {}

as interfaces base do IComboBox são IControl , ITextBox e IListBox .the base interfaces of IComboBox are IControl, ITextBox, and IListBox.

Em outras palavras, a IComboBox interface acima herda membros SetText e SetItems também Paint .In other words, the IComboBox interface above inherits members SetText and SetItems as well as Paint.

Cada interface base de uma interface deve ser de saída segura (segurança de variação).Every base interface of an interface must be output-safe (Variance safety). Uma classe ou struct que implementa uma interface também implementa implicitamente todas as interfaces base da interface.A class or struct that implements an interface also implicitly implements all of the interface's base interfaces.

Corpo da interfaceInterface body

A interface_body de uma interface define os membros da interface.The interface_body of an interface defines the members of the interface.

interface_body
    : '{' interface_member_declaration* '}'
    ;

Membros da interfaceInterface members

Os membros de uma interface são os membros herdados das interfaces base e os membros declarados pela própria interface.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
    ;

Uma declaração de interface pode declarar zero ou mais membros.An interface declaration may declare zero or more members. Os membros de uma interface devem ser métodos, propriedades, eventos ou indexadores.The members of an interface must be methods, properties, events, or indexers. Uma interface não pode conter constantes, campos, operadores, construtores de instância, destruidores ou tipos, nem uma interface que contenha membros estáticos de qualquer tipo.An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.

Todos os membros de interface implicitamente têm acesso público.All interface members implicitly have public access. É um erro de tempo de compilação para declarações de membro de interface para incluir qualquer modificador.It is a compile-time error for interface member declarations to include any modifiers. Em particular, os membros de interfaces não podem ser declarados com os modificadores,,,,,,, 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.

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

declara uma interface que contém um dos tipos de membros possíveis: um método, uma propriedade, um evento e um indexador.declares an interface that contains one each of the possible kinds of members: A method, a property, an event, and an indexer.

Um interface_declaration cria um novo espaço de declaração (declarações) e os interface_member_declaration s imediatamente contidos pelo interface_declaration introduzem novos membros nesse espaço de declaração.An interface_declaration creates a new declaration space (Declarations), and the interface_member_declaration s immediately contained by the interface_declaration introduce new members into this declaration space. As regras a seguir se aplicam a interface_member_declaration s:The following rules apply to interface_member_declaration s:

  • O nome de um método deve ser diferente dos nomes de todas as propriedades e eventos declarados na mesma interface.The name of a method must differ from the names of all properties and events declared in the same interface. Além disso, a assinatura (assinaturas e sobrecarga) de um método deve ser diferente das assinaturas de todos os outros métodos declarados na mesma interface, e dois métodos declarados na mesma interface podem não ter assinaturas que diferem exclusivamente pelo ref e 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.
  • O nome de uma propriedade ou evento deve ser diferente dos nomes de todos os outros membros declarados na mesma interface.The name of a property or event must differ from the names of all other members declared in the same interface.
  • A assinatura de um indexador deve ser diferente das assinaturas de todos os outros indexadores declarados na mesma interface.The signature of an indexer must differ from the signatures of all other indexers declared in the same interface.

Os membros herdados de uma interface não fazem parte especificamente do espaço de declaração da interface.The inherited members of an interface are specifically not part of the declaration space of the interface. Assim, uma interface tem permissão para declarar um membro com o mesmo nome ou assinatura que um membro herdado.Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. Quando isso ocorre, o membro da interface derivada é dito para ocultar o membro da interface base.When this occurs, the derived interface member is said to hide the base interface member. Ocultar um membro herdado não é considerado um erro, mas faz com que o compilador emita um aviso.Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. Para suprimir o aviso, a declaração do membro de interface derivada deve incluir um new modificador para indicar que o membro derivado destina-se a ocultar o membro 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. Este tópico é abordado mais detalhadamente em ocultar por meio de herança.This topic is discussed further in Hiding through inheritance.

Se um new modificador for incluído em uma declaração que não oculta um membro herdado, um aviso será emitido para esse efeito.If a new modifier is included in a declaration that doesn't hide an inherited member, a warning is issued to that effect. Esse aviso é suprimido com a remoção do new modificador.This warning is suppressed by removing the new modifier.

Observe que os membros da classe object não são, estritamente falando, membros de qualquer interface (membros da interface).Note that the members in class object are not, strictly speaking, members of any interface (Interface members). No entanto, os membros da classe object estão disponíveis por meio de pesquisa de membros em qualquer tipo de interface (pesquisa de membros).However, the members in class object are available via member lookup in any interface type (Member lookup).

Métodos de interfaceInterface methods

Métodos de interface são declarados usando interface_method_declaration s:Interface methods are declared using interface_method_declaration s:

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

Os atributos, return_type, identificador e formal_parameter_list de uma declaração de método de interface têm o mesmo significado que os de uma declaração de método em uma classe (métodos).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). Uma declaração de método de interface não tem permissão para especificar um corpo de método, e a declaração, portanto, sempre termina com um ponto e vírgula.An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon.

Cada tipo de parâmetro formal de um método de interface deve ser de entrada segura (segurança de variação) e o tipo de retorno deve ser void ou de saída seguro.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. Além disso, cada restrição de tipo de classe, restrição de tipo de interface e restrição de parâmetro de tipo em qualquer parâmetro de tipo do método deve ser de entrada segura.Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method must be input-safe.

Essas regras garantem que qualquer uso covariante ou contravariant da interface permaneça de tipo seguro.These rules ensure that any covariant or contravariant usage of the interface remains type-safe. Por exemplo,For example,

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

é ilegal porque o uso de T como uma restrição de parâmetro de tipo em U não é de entrada segura.is illegal because the usage of T as a type parameter constraint on U is not input-safe.

Essa restrição não estava em vigor, seria possível violar a segurança do tipo da seguinte maneira: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>();

Essa é, na verdade, uma chamada para C.M<E> .This is actually a call to C.M<E>. Mas essa chamada exige que E derive de D , portanto, a segurança do tipo seria violada aqui.But that call requires that E derive from D, so type safety would be violated here.

Propriedades de interfaceInterface properties

As propriedades da interface são declaradas usando interface_property_declaration s:Interface properties are declared using interface_property_declaration s:

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

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

Os atributos, o tipo e o identificador de uma declaração de propriedade de interface têm o mesmo significado que os de uma declaração de propriedade em uma classe (Propriedades).The attributes, type, and identifier of an interface property declaration have the same meaning as those of a property declaration in a class (Properties).

Os acessadores de uma declaração de propriedade de interface correspondem aos acessadores de uma declaração de propriedade de classe (acessadores), exceto que o corpo do acessador sempre deve ser um ponto e vírgula.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. Portanto, os acessadores simplesmente indicam se a propriedade é de leitura/gravação, somente leitura ou somente gravação.Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.

O tipo de uma propriedade de interface deve ser de saída segura se houver um acessador get e deve ser de entrada segura se houver um acessador 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.

Eventos de interfaceInterface events

Eventos de interface são declarados usando interface_event_declaration s:Interface events are declared using interface_event_declaration s:

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

Os atributos, o tipo e o identificador de uma declaração de evento de interface têm o mesmo significado que os de uma declaração de evento em uma classe (eventos).The attributes, type, and identifier of an interface event declaration have the same meaning as those of an event declaration in a class (Events).

O tipo de um evento de interface deve ser de entrada segura.The type of an interface event must be input-safe.

Indexadores de interfaceInterface indexers

Indexadores de interface são declarados usando interface_indexer_declaration s:Interface indexers are declared using interface_indexer_declaration s:

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

Os atributos, o tipo e a formal_parameter_list de uma declaração de indexador de interface têm o mesmo significado que os de uma declaração de indexador em uma classe (indexadores).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).

Os acessadores de uma declaração de indexador de interface correspondem aos acessadores de uma declaração de indexador de classe (indexadores), exceto que o corpo do acessador sempre deve ser um ponto e vírgula.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. Assim, os acessadores simplesmente indicam se o indexador é de leitura/gravação, somente leitura ou somente gravação.Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.

Todos os tipos de parâmetro formais de um indexador de interface devem ser de entrada segura.All the formal parameter types of an interface indexer must be input-safe . Além disso, qualquer out ref tipo de parâmetro ou formal também deve ser de saída segura.In addition, any out or ref formal parameter types must also be output-safe. Observe que até mesmo out os parâmetros devem ser de entrada segura, devido a uma limitação da plataforma de execução subjacente.Note that even out parameters are required to be input-safe, due to a limitation of the underlying execution platform.

O tipo de um indexador de interface deve ser seguro para saída se houver um acessador get e deve ser de entrada segura se houver um acessador 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.

Acesso de membro de interfaceInterface member access

Os membros da interface são acessados por meio de acesso de membro (acesso de membro) e expressões de acesso do indexador (acesso aoindexador) do formulário I.M e I[A] , em que I é um tipo de interface, M é um método, propriedade ou evento desse tipo de interface e A é uma lista de argumentos do indexador.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.

Para interfaces que são estritamente herança única (cada interface na cadeia de herança tem exatamente zero ou uma interface de base direta), os efeitos da pesquisa de Membros (pesquisa de membros), da invocação de método (invocações de método) e das regras de acesso do indexador (acesso ao indexador) são exatamente iguais aos de classes e structs: Membros mais derivados ocultam Membros derivados menores com o mesmo nome ou assinatura.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. No entanto, para interfaces de várias heranças, as ambiguidades podem ocorrer quando duas ou mais interfaces base não relacionadas declaram Membros com o mesmo nome ou assinatura.However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. Esta seção mostra vários exemplos dessas situações.This section shows several examples of such situations. Em todos os casos, as conversões explícitas podem ser usadas para resolver as ambiguidades.In all cases, explicit casts can be used to resolve the ambiguities.

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

as duas primeiras instruções causam erros de tempo de compilação porque a pesquisa de membro (pesquisa de membro) de Count no IListCounter é ambígua.the first two statements cause compile-time errors because the member lookup (Member lookup) of Count in IListCounter is ambiguous. Conforme ilustrado pelo exemplo, a ambiguidade é resolvida pela conversão x para o tipo de interface base apropriado.As illustrated by the example, the ambiguity is resolved by casting x to the appropriate base interface type. Tais conversões não têm custos de tempo de execução — elas simplesmente consistem em exibir a instância como um tipo menos derivado em tempo de compilação.Such casts have no run-time costs—they merely consist of viewing the instance as a less derived type at compile-time.

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

a invocação n.Add(1) seleciona IInteger.Add aplicando as regras de resolução de sobrecarga da resolução de sobrecarga.the invocation n.Add(1) selects IInteger.Add by applying the overload resolution rules of Overload resolution. Da mesma forma, a invocação é n.Add(1.0) selecionada IDouble.Add .Similarly the invocation n.Add(1.0) selects IDouble.Add. Quando as conversões explícitas são inseridas, há apenas um método candidato e, portanto, nenhuma ambiguidade.When explicit casts are inserted, there is only one candidate method, and thus no ambiguity.

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

o IBase.F membro é oculto pelo ILeft.F membro.the IBase.F member is hidden by the ILeft.F member. A invocação d.F(1) , portanto ILeft.F , é selecionada, embora IBase.F pareça não estar oculta no caminho de acesso que leva 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.

A regra intuitiva para ocultar em interfaces de várias heranças é simplesmente: se um membro estiver oculto em qualquer caminho de acesso, ele ficará oculto em todos os caminhos de acesso.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. Como o caminho de acesso de IDerived para ILeft para IBase ocultar IBase.F , o membro também fica oculto no caminho de acesso de IDerived para 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.

Nomes de membros de interface totalmente qualificadosFully qualified interface member names

Um membro de interface, às vezes, é referido por seu nome totalmente qualificado.An interface member is sometimes referred to by its fully qualified name. O nome totalmente qualificado de um membro de interface consiste no nome da interface na qual o membro é declarado, seguido por um ponto, seguido pelo nome do membro.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. O nome totalmente qualificado de um membro faz referência à interface na qual o membro é declarado.The fully qualified name of a member references the interface in which the member is declared. Por exemplo, considerando as declaraçõesFor example, given the declarations

interface IControl
{
    void Paint();
}

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

o nome totalmente qualificado de Paint é IControl.Paint e o nome totalmente qualificado de SetText é ITextBox.SetText .the fully qualified name of Paint is IControl.Paint and the fully qualified name of SetText is ITextBox.SetText.

No exemplo acima, não é possível fazer referência a Paint as ITextBox.Paint .In the example above, it is not possible to refer to Paint as ITextBox.Paint.

Quando uma interface faz parte de um namespace, o nome totalmente qualificado de um membro de interface inclui o nome do namespace.When an interface is part of a namespace, the fully qualified name of an interface member includes the namespace name. Por exemplo,For example

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

Aqui, o nome totalmente qualificado do Clone método é System.ICloneable.Clone .Here, the fully qualified name of the Clone method is System.ICloneable.Clone.

Implementações de interfacesInterface implementations

As interfaces podem ser implementadas por classes e estruturas.Interfaces may be implemented by classes and structs. Para indicar que uma classe ou struct implementa diretamente uma interface, o identificador de interface é incluído na lista de classes base da classe ou estrutura.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. Por exemplo:For example:

interface ICloneable
{
    object Clone();
}

interface IComparable
{
    int CompareTo(object other);
}

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

Uma classe ou estrutura que implementa diretamente uma interface também implementa diretamente todas as interfaces base da interface implicitamente.A class or struct that directly implements an interface also directly implements all of the interface's base interfaces implicitly. Isso é verdadeiro mesmo que a classe ou struct não liste explicitamente todas as interfaces base na lista de classes base.This is true even if the class or struct doesn't explicitly list all base interfaces in the base class list. Por exemplo:For example:

interface IControl
{
    void Paint();
}

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

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

Aqui, a classe TextBox implementa IControl e ITextBox .Here, class TextBox implements both IControl and ITextBox.

Quando uma classe C implementa diretamente uma interface, todas as classes derivadas de C também implementam a interface implicitamente.When a class C directly implements an interface, all classes derived from C also implement the interface implicitly. As interfaces base especificadas em uma declaração de classe podem ser tipos de interface construídos (tipos construídos).The base interfaces specified in a class declaration can be constructed interface types (Constructed types). Uma interface base não pode ser um parâmetro de tipo por conta própria, embora possa envolver os parâmetros de tipo que estão no escopo.A base interface cannot be a type parameter on its own, though it can involve the type parameters that are in scope. O código a seguir ilustra como uma classe pode implementar e estender tipos construídos: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> {}

As interfaces base de uma declaração de classe genérica devem satisfazer a regra de exclusividade descrita em exclusividade das interfaces implementadas.The base interfaces of a generic class declaration must satisfy the uniqueness rule described in Uniqueness of implemented interfaces.

Implementações explícitas de membro de interfaceExplicit interface member implementations

Para fins de implementação de interfaces, uma classe ou estrutura pode declarar implementações explícitas de membro de interface.For purposes of implementing interfaces, a class or struct may declare explicit interface member implementations. Uma implementação de membro de interface explícita é uma declaração de método, propriedade, evento ou indexador que faz referência a um nome de membro de interface totalmente qualificado.An explicit interface member implementation is a method, property, event, or indexer declaration that references a fully qualified interface member name. Por exemplo,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) {...}
}

Aqui IDictionary<int,T>.this IDictionary<int,T>.Add estão as implementações explícitas de membros de interface.Here IDictionary<int,T>.this and IDictionary<int,T>.Add are explicit interface member implementations.

Em alguns casos, o nome de um membro de interface pode não ser apropriado para a classe de implementação; nesse caso, o membro de interface pode ser implementado usando a implementação de membro de interface explícita.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. Uma classe que implementa uma abstração de arquivo, por exemplo, provavelmente implementaria uma Close função de membro que tem o efeito de liberar o recurso de arquivo e implementaria o Dispose método da IDisposable interface usando a implementação de membro de interface explícita: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);
    }
}

Não é possível acessar uma implementação de membro de interface explícita por meio de seu nome totalmente qualificado em uma invocação de método, acesso de propriedade ou acesso de indexador.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. Uma implementação de membro de interface explícita só pode ser acessada por meio de uma instância de interface e, nesse caso, é referenciada simplesmente pelo seu nome de membro.An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.

É um erro de tempo de compilação para uma implementação de membro de interface explícita para incluir modificadores de acesso e é um erro de tempo de compilação para incluir os modificadores 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.

Implementações explícitas de membros de interface têm características de acessibilidade diferentes de outros membros.Explicit interface member implementations have different accessibility characteristics than other members. Como implementações explícitas de membros de interface nunca são acessíveis por meio de seu nome totalmente qualificado em uma invocação de método ou um acesso de propriedade, elas estão em um aspecto particular.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. No entanto, como eles podem ser acessados por meio de uma instância de interface, eles também são públicos.However, since they can be accessed through an interface instance, they are in a sense also public.

Implementações explícitas de membro de interface atendem a duas finalidades principais:Explicit interface member implementations serve two primary purposes:

  • Como as implementações explícitas de membro de interface não são acessíveis por meio de instâncias de classe ou struct, elas permitem que as implementações de interface sejam excluídas da interface pública de uma classe ou estrutura.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. Isso é particularmente útil quando uma classe ou estrutura implementa uma interface interna que não é de interesse de um consumidor dessa 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.
  • Implementações explícitas de membros de interface permitem a desambiguidade de membros de interface com a mesma assinatura.Explicit interface member implementations allow disambiguation of interface members with the same signature. Sem implementações explícitas de membros de interface, seria impossível que uma classe ou estrutura tenha diferentes implementações de membros de interface com a mesma assinatura e tipo de retorno, como seria impossível para uma classe ou estrutura ter qualquer implementação em todos os membros da interface com a mesma assinatura, mas com tipos de retorno diferentes.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.

Para que uma implementação de membro de interface explícita seja válida, a classe ou struct deve nomear uma interface em sua lista de classes base que contém um membro cujos nomes totalmente qualificados, tipos, e tipo de parâmetro correspondem exatamente aos da implementação de membro de interface explícita.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. Portanto, na seguinte classeThus, in the following class

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

a declaração de IComparable.CompareTo resulta em um erro de tempo de compilação porque IComparable não está listado na lista de classes base de Shape e não é uma interface base do 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. Da mesma forma, nas declaraçõesLikewise, in the declarations

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

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

a declaração do ICloneable.Clone nos Ellipse resulta em um erro de tempo de compilação porque ICloneable não está explicitamente listado na lista de classes base do 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.

O nome totalmente qualificado de um membro de interface deve referenciar a interface na qual o membro foi declarado.The fully qualified name of an interface member must reference the interface in which the member was declared. Portanto, nas declaraçõesThus, 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) {...}
}

a implementação explícita de membro de interface de Paint deve ser escrita como IControl.Paint .the explicit interface member implementation of Paint must be written as IControl.Paint.

Exclusividade das interfaces implementadasUniqueness of implemented interfaces

As interfaces implementadas por uma declaração de tipo genérico devem permanecer exclusivas para todos os tipos construídos possíveis.The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. Sem essa regra, seria impossível determinar o método correto a ser chamado para determinados tipos construídos.Without this rule, it would be impossible to determine the correct method to call for certain constructed types. Por exemplo, suponha que uma declaração de classe genérica tenha permissão para ser escrita da seguinte maneira: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() {...}
}

Isso era permitido, seria impossível determinar qual código deve ser executado no seguinte caso: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();

Para determinar se a lista de interfaces de uma declaração de tipo genérico é válida, as etapas a seguir são executadas:To determine if the interface list of a generic type declaration is valid, the following steps are performed:

  • Permite que L a lista de interfaces seja especificada diretamente em uma declaração de classe, struct ou interface genérica C .Let L be the list of interfaces directly specified in a generic class, struct, or interface declaration C.
  • Adicione a L qualquer interface base das interfaces já existentes no L .Add to L any base interfaces of the interfaces already in L.
  • Remova as duplicatas de L .Remove any duplicates from L.
  • Se qualquer tipo construído possível criado a partir de C , depois que os argumentos de tipo forem substituídos L , fazer com que duas interfaces L sejam idênticas; a declaração de C é inválida.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. Declarações de restrição não são consideradas ao determinar todos os tipos construídos possíveis.Constraint declarations are not considered when determining all possible constructed types.

Na declaração de classe X acima, a lista de interface L consiste em I<U> e I<V> .In the class declaration X above, the interface list L consists of I<U> and I<V>. A declaração é inválida porque qualquer tipo construído com U e V sendo o mesmo tipo faria com que essas duas interfaces fossem tipos idênticos.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.

É possível que as interfaces especificadas em diferentes níveis de herança sejam unificadas: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() {...}
}

Esse código é válido mesmo que Derived<U,V> implemente o I<U> e o I<V> .This code is valid even though Derived<U,V> implements both I<U> and I<V>. O códigoThe code

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

invoca o método no Derived , desde que Derived<int,int> efetivamente Reimplemente I<int> (reimplementação de interface).invokes the method in Derived, since Derived<int,int> effectively re-implements I<int> (Interface re-implementation).

Implementação de métodos genéricosImplementation of generic methods

Quando um método genérico implementa implicitamente um método de interface, as restrições dadas para cada parâmetro de tipo de método devem ser equivalentes em ambas as declarações (depois que quaisquer parâmetros de tipo de interface são substituídos pelos argumentos de tipo apropriados), em que os parâmetros de tipo de método são identificados por posições ordinais, da esquerda para a direita.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.

No entanto, quando um método genérico implementa explicitamente um método de interface, nenhuma restrição é permitida no método de implementação.When a generic method explicitly implements an interface method, however, no constraints are allowed on the implementing method. Em vez disso, as restrições são herdadas do método de 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
}

O método C.F<T> implementa implicitamente I<object,C,string>.F<T> .The method C.F<T> implicitly implements I<object,C,string>.F<T>. Nesse caso, C.F<T> o não é necessário (nem permitido) para especificar a restrição T:object , pois object é uma restrição implícita em todos os parâmetros de tipo.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. O método C.G<T> implementa implicitamente I<object,C,string>.G<T> porque as restrições correspondem àquelas na interface, depois que os parâmetros de tipo de interface são substituídos pelos argumentos de tipo correspondentes.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. A restrição para C.H<T> o método é um erro porque os tipos lacrados ( string nesse caso) não podem ser usados como restrições.The constraint for method C.H<T> is an error because sealed types (string in this case) cannot be used as constraints. Omitir a restrição também seria um erro, já que restrições de implementações do método de interface implícita são necessárias para corresponder.Omitting the constraint would also be an error since constraints of implicit interface method implementations are required to match. Portanto, é impossível implementar implicitamente I<object,C,string>.H<T> .Thus, it is impossible to implicitly implement I<object,C,string>.H<T>. Este método de interface só pode ser implementado usando uma implementação de membro de interface explícita: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);
    }
}

Neste exemplo, a implementação de membro de interface explícita invoca um método público com restrições estritamente mais fracas.In this example, the explicit interface member implementation invokes a public method having strictly weaker constraints. Observe que a atribuição de t para s é válida desde que T herde uma restrição de T:string , mesmo que essa restrição não seja expressa no código-fonte.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.

Mapeamento de interfaceInterface mapping

Uma classe ou estrutura deve fornecer implementações de todos os membros das interfaces que estão listadas na lista classe base da classe ou estrutura.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. O processo de localizar implementações de membros de interface em uma classe de implementação ou struct é conhecido como mapeamento de interface.The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.

O mapeamento de interface para uma classe ou struct C localiza uma implementação para cada membro de cada interface especificada na lista de classes base do 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. A implementação de um membro de interface específico I.M , em que I é a interface na qual o membro M é declarado, é determinada examinando cada classe ou struct S , começando com C e repetindo cada classe base sucessiva de C , até que uma correspondência seja localizada: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:

  • Se S contiver uma declaração de uma implementação de membro de interface explícita que corresponda I M a e, esse membro será a implementação 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.
  • Caso contrário, se S contiver uma declaração de um membro público não estático que corresponda M , esse membro será a implementação 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. Se mais de um membro corresponder, ele não especificará qual membro é a implementação de I.M .If more than one member matches, it is unspecified which member is the implementation of I.M. Essa situação só pode ocorrer se S for um tipo construído em que os dois membros como declarados no tipo genérico tenham assinaturas diferentes, mas os argumentos de tipo tornam suas assinaturas idênticas.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.

Ocorrerá um erro de tempo de compilação se não for possível localizar implementações para todos os membros de todas as interfaces especificadas na lista de classes 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. Observe que os membros de uma interface incluem os membros que são herdados das interfaces base.Note that the members of an interface include those members that are inherited from base interfaces.

Para fins de mapeamento de interface, um membro de classe A corresponde a um membro de interface B quando:For purposes of interface mapping, a class member A matches an interface member B when:

  • A e B são métodos, e as listas de parâmetro Name, Type e formal de A e B são idênticas.A and B are methods, and the name, type, and formal parameter lists of A and B are identical.
  • A e B são propriedades, o nome e o tipo de A e B são idênticos e A têm os mesmos acessadores que (tem B A permissão para ter acessadores adicionais se não for uma implementação de membro de interface explícita).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 e B são eventos, e o nome e o tipo de A e B são idênticos.A and B are events, and the name and type of A and B are identical.
  • A e B são indexadores, o tipo e as listas de parâmetros formais de A e B são idênticos e A têm os mesmos acessadores como B ( A é permitido ter acessadores adicionais se não for uma implementação de membro de interface explícita).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).

As implicações notáveis do algoritmo de mapeamento de interface são:Notable implications of the interface mapping algorithm are:

  • Implementações explícitas de membros de interface têm precedência sobre outros membros na mesma classe ou struct ao determinar o membro Class ou struct que implementa um membro de 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.
  • Nem membros não públicos nem estáticos participam do mapeamento de interface.Neither non-public nor static members participate in interface mapping.

No exemploIn the example

interface ICloneable
{
    object Clone();
}

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

o ICloneable.Clone membro de C se torna a implementação do Clone no ICloneable porque as implementações explícitas de membros de interface têm precedência sobre outros membros.the ICloneable.Clone member of C becomes the implementation of Clone in ICloneable because explicit interface member implementations take precedence over other members.

Se uma classe ou struct implementa duas ou mais interfaces que contêm um membro com os mesmos tipos de nome, tipo e parâmetro, é possível mapear cada um desses membros de interface em um único membro de classe ou 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. Por exemplo,For example

interface IControl
{
    void Paint();
}

interface IForm
{
    void Paint();
}

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

Aqui, os Paint métodos de IControl e IForm são mapeados para o Paint método no Page .Here, the Paint methods of both IControl and IForm are mapped onto the Paint method in Page. É claro que também é possível ter implementações de membros de interface explícita separadas para os dois métodos.It is of course also possible to have separate explicit interface member implementations for the two methods.

Se uma classe ou estrutura implementar uma interface que contenha Membros ocultos, alguns membros deverão ser necessariamente implementados por meio de implementações de membro de interface explícita.If a class or struct implements an interface that contains hidden members, then some members must necessarily be implemented through explicit interface member implementations. Por exemplo,For example

interface IBase
{
    int P { get; }
}

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

Uma implementação dessa interface exigiria pelo menos uma implementação de membro de interface explícita e usaria um dos seguintes formuláriosAn 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() {...}
}

Quando uma classe implementa várias interfaces que têm a mesma interface base, pode haver apenas uma implementação da interface base.When a class implements multiple interfaces that have the same base interface, there can be only one implementation of the base interface. No exemploIn 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) {...}
}

Não é possível ter implementações separadas para o IControl nome na lista de classes base, o IControl herdado por ITextBox e o IControl herdado por 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. Na verdade, não há nenhuma noção de uma identidade separada para essas interfaces.Indeed, there is no notion of a separate identity for these interfaces. Em vez disso, as implementações de ITextBox e IListBox compartilham a mesma implementação de IControl , e ComboBox são simplesmente consideradas para implementar três interfaces, IControl , ITextBox e 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.

Os membros de uma classe base participam do mapeamento de interface.The members of a base class participate in interface mapping. No exemploIn the example

interface Interface1
{
    void F();
}

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

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

o método F no Class1 é usado na Class2 implementação de Interface1 .the method F in Class1 is used in Class2's implementation of Interface1.

Herança de implementação de interfaceInterface implementation inheritance

Uma classe herda todas as implementações de interface fornecidas por suas classes base.A class inherits all interface implementations provided by its base classes.

Sem a reimplementação explícita de uma interface, uma classe derivada não pode alterar os mapeamentos de interface herdados de suas classes base.Without explicitly re-implementing an interface, a derived class cannot in any way alter the interface mappings it inherits from its base classes. Por exemplo, nas declaraçõesFor example, in the declarations

interface IControl
{
    void Paint();
}

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

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

o Paint método em TextBox oculta o Paint método em Control , mas não altera o mapeamento de Control.Paint para e as IControl.Paint chamadas para as instâncias de Paint classe e instâncias de interface terão os seguintes efeitosthe 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();

No entanto, quando um método de interface é mapeado em um método virtual em uma classe, é possível que as classes derivadas substituam o método virtual e alterem a implementação da 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. Por exemplo, reescrever as declarações acima paraFor example, rewriting the declarations above to

interface IControl
{
    void Paint();
}

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

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

os efeitos a seguir agora serão observadosthe 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();

Como as implementações explícitas de membro de interface não podem ser declaradas como virtuais, não é possível substituir uma implementação de membro de interface explícita.Since explicit interface member implementations cannot be declared virtual, it is not possible to override an explicit interface member implementation. No entanto, é perfeitamente válido para uma implementação de membro de interface explícita chamar outro método, e esse outro método pode ser declarado como virtual para permitir que as classes derivadas a substituam.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. Por exemplo,For example

interface IControl
{
    void Paint();
}

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

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

Aqui, as classes derivadas de Control podem especializar a implementação do IControl.Paint substituindo o PaintControl método.Here, classes derived from Control can specialize the implementation of IControl.Paint by overriding the PaintControl method.

Reimplementação da interfaceInterface re-implementation

Uma classe que herda uma implementação de interface tem permissão para implementar a interface novamente , incluindo-a na lista de classes base.A class that inherits an interface implementation is permitted to re-implement the interface by including it in the base class list.

Uma nova implementação de uma interface segue exatamente as mesmas regras de mapeamento de interface que uma implementação inicial de uma interface.A re-implementation of an interface follows exactly the same interface mapping rules as an initial implementation of an interface. Portanto, o mapeamento de interface herdado não tem nenhum efeito no mapeamento de interface estabelecido para a reimplementação da interface.Thus, the inherited interface mapping has no effect whatsoever on the interface mapping established for the re-implementation of the interface. Por exemplo, nas declaraçõesFor example, in the declarations

interface IControl
{
    void Paint();
}

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

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

o fato de que Control mapas IControl.Paint em Control.IControl.Paint não afeta a reimplementação no MyControl , que mapeia IControl.Paint para 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.

As declarações de membro público herdadas e as declarações de membro de interface explícita herdadas participam do processo de mapeamento de interface para interfaces reimplementadas.Inherited public member declarations and inherited explicit interface member declarations participate in the interface mapping process for re-implemented interfaces. Por exemplo,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() {}
}

Aqui, a implementação do IMethods no Derived mapeia os métodos de interface para Derived.F , Base.IMethods.G , Derived.IMethods.H e 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.

Quando uma classe implementa uma interface, ela também implementa implicitamente todas as interfaces base dessa interface.When a class implements an interface, it implicitly also implements all of that interface's base interfaces. Da mesma forma, uma reimplementação de uma interface também é implicitamente uma reimplementação de todas as interfaces base da interface.Likewise, a re-implementation of an interface is also implicitly a re-implementation of all of the interface's base interfaces. Por exemplo,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() {...}
}

Aqui, a nova implementação de IDerived também reimplementa IBase , mapeamento IBase.F para D.F .Here, the re-implementation of IDerived also re-implements IBase, mapping IBase.F onto D.F.

Interfaces e classes abstratasAbstract classes and interfaces

Como uma classe não abstrata, uma classe abstrata deve fornecer implementações de todos os membros das interfaces que estão listadas na lista classe base da 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. No entanto, uma classe abstrata é permitida para mapear métodos de interface em métodos abstratos.However, an abstract class is permitted to map interface methods onto abstract methods. Por exemplo,For example

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

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

Aqui, a implementação de IMethods mapas F e G em métodos abstratos, que deve ser substituída em classes não abstratas que derivam 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.

Observe que as implementações explícitas de membros de interface não podem ser abstratas, mas implementações explícitas de membros de interface, obviamente, têm permissão para chamar métodos abstract.Note that explicit interface member implementations cannot be abstract, but explicit interface member implementations are of course permitted to call abstract methods. Por exemplo,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();
}

Aqui, as classes não abstratas que derivam de C seriam necessárias para substituir FF e GG , portanto, fornecer a implementação real 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.