InterfacesInterfaces
Una interfaz define un contrato.An interface defines a contract. Una clase o estructura que implementa una interfaz debe adherirse a su contrato.A class or struct that implements an interface must adhere to its contract. Una interfaz puede heredar de varias interfaces base, y una clase o estructura puede implementar varias interfaces.An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces.
Las interfaces pueden contener métodos, propiedades, eventos e indizadores.Interfaces can contain methods, properties, events, and indexers. La propia interfaz no proporciona implementaciones para los miembros que define.The interface itself does not provide implementations for the members that it defines. La interfaz simplemente especifica los miembros que deben ser proporcionados por clases o Structs que implementan la interfaz.The interface merely specifies the members that must be supplied by classes or structs that implement the interface.
Declaraciones de interfazInterface declarations
Una interface_declaration es una type_declaration (declaraciones de tipos) que declara un nuevo tipo de interfaz.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 consta de un conjunto opcional de atributos (atributos), seguido de un conjunto opcional de interface_modifier s (modificadores de interfaz), seguido de un partial
modificador opcional, seguido de la palabra clave interface
y un identificador que asigna un nombre a la interfaz, seguido de una especificación de variant_type_parameter_list opcional (listas de parámetros de tipo variante), seguida de una especificación de interface_base opcional (interfaces base), seguida de una especificación de type_parameter_constraints_clause s opcional (restricciones de parámetro de tipo), seguida de un interface_body (cuerpo de la interfaz), opcionalmenteAn 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 interfazInterface modifiers
Un interface_declaration puede incluir opcionalmente una secuencia de modificadores de interfaz:An interface_declaration may optionally include a sequence of interface modifiers:
interface_modifier
: 'new'
| 'public'
| 'protected'
| 'internal'
| 'private'
| interface_modifier_unsafe
;
Es un error en tiempo de compilación que el mismo modificador aparezca varias veces en una declaración de interfaz.It is a compile-time error for the same modifier to appear multiple times in an interface declaration.
El new
modificador solo se permite en interfaces definidas dentro de una clase.The new
modifier is only permitted on interfaces defined within a class. Especifica que la interfaz oculta un miembro heredado con el mismo nombre, tal y como se describe en el modificador New.It specifies that the interface hides an inherited member by the same name, as described in The new modifier.
Los public
protected
internal
modificadores,, y private
controlan la accesibilidad de la interfaz.The public
, protected
, internal
, and private
modifiers control the accessibility of the interface. Dependiendo del contexto en el que se produce la declaración de la interfaz, solo se pueden permitir algunos de estos modificadores (sedeclarará la accesibilidad).Depending on the context in which the interface declaration occurs, only some of these modifiers may be permitted (Declared accessibility).
Unmodifier (modificador)Partial modifier
El partial
modificador indica que este interface_declaration es una declaración de tipos parciales.The partial
modifier indicates that this interface_declaration is a partial type declaration. Varias declaraciones de interfaz parcial con el mismo nombre dentro de una declaración de tipo o espacio de nombres envolvente se combinan para formar una declaración de interfaz, siguiendo las reglas especificadas en tipos parciales.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 varianteVariant type parameter lists
Las listas de parámetros de tipo variante solo se pueden producir en tipos de interfaz y delegado.Variant type parameter lists can only occur on interface and delegate types. La diferencia de los type_parameter_list normales es el variance_annotation opcional en 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'
;
Si la anotación de varianza es out
, se dice que el parámetro de tipo es *covariante _.If the variance annotation is out
, the type parameter is said to be *covariant _. Si la anotación de varianza es in
, se dice que el parámetro de tipo es contravariante.If the variance annotation is in
, the type parameter is said to be contravariant. Si no hay ninguna anotación de varianza, se dice que el parámetro de tipo es _ invariable *.If there is no variance annotation, the type parameter is said to be _*invariant**.
En el ejemploIn the example
interface C<out X, in Y, Z>
{
X M(Y y);
Z P { get; set; }
}
X
es covariante, Y
es contravariante y Z
es invariable.X
is covariant, Y
is contravariant and Z
is invariant.
Seguridad de la varianzaVariance safety
La aparición de anotaciones de varianza en la lista de parámetros de tipo de un tipo restringe los lugares en los que se pueden producir tipos en la declaración de tipos.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 tipo T
es Output-Unsafe si uno de los siguientes contiene:A type T
is output-unsafe if one of the following holds:
T
es un parámetro de tipo contravarianteT
is a contravariant type parameterT
es un tipo de matriz con un tipo de elemento de salida no seguroT
is an array type with an output-unsafe element typeT
es un tipo de interfaz o delegadoS<A1,...,Ak>
construido a partir de un tipo genéricoS<X1,...,Xk>
en el que para al menos unoAi
de los elementos siguientes contiene:T
is an interface or delegate typeS<A1,...,Ak>
constructed from a generic typeS<X1,...,Xk>
where for at least oneAi
one of the following holds:Xi
es covariante o invariable yAi
es una salida no segura.Xi
is covariant or invariant andAi
is output-unsafe.Xi
es contravariante o invariable yAi
es seguro para la entrada.Xi
is contravariant or invariant andAi
is input-safe.
Un tipo T
es una entrada no segura si uno de los siguientes contiene:A type T
is input-unsafe if one of the following holds:
T
es un parámetro de tipo covarianteT
is a covariant type parameterT
es un tipo de matriz con un tipo de elemento no seguro de entradaT
is an array type with an input-unsafe element typeT
es un tipo de interfaz o delegadoS<A1,...,Ak>
construido a partir de un tipo genéricoS<X1,...,Xk>
en el que para al menos unoAi
de los elementos siguientes contiene:T
is an interface or delegate typeS<A1,...,Ak>
constructed from a generic typeS<X1,...,Xk>
where for at least oneAi
one of the following holds:Xi
es covariante o invariable yAi
es de entrada no segura.Xi
is covariant or invariant andAi
is input-unsafe.Xi
es contravariante o invariable yAi
es Output-Unsafe.Xi
is contravariant or invariant andAi
is output-unsafe.
De forma intuitiva, se prohíbe un tipo de salida no segura en una posición de salida y se prohíbe un tipo de entrada no segura en una posición de entrada.Intuitively, an output-unsafe type is prohibited in an output position, and an input-unsafe type is prohibited in an input position.
Un tipo es Output-Safe _ si no es de salida, y _ Safe-Safe si no es de entrada-no segura.A type is output-safe _ if it is not output-unsafe, and _ input-safe if it is not input-unsafe.
Conversión de varianzaVariance conversion
El propósito de las anotaciones de varianza es proporcionar conversiones más flexibles (pero todavía con seguridad de tipos) a los tipos de interfaz y delegado.The purpose of variance annotations is to provide for more lenient (but still type safe) conversions to interface and delegate types. Para este fin, las definiciones de las conversiones implícitas (conversionesimplícitas) y explícitas (conversiones explícitas) hacen uso de la noción de Variance-Convertibility, que se define de la siguiente manera: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 tipo T<A1,...,An>
es una varianza de la conversión a un tipo T<B1,...,Bn>
si T
es una interfaz o un tipo de delegado declarado con los parámetros T<X1,...,Xn>
de tipo variante y para cada parámetro Xi
de tipo variante uno de los siguientes: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
es covariante y existe una referencia implícita o una conversión de identidad deAi
aBi
Xi
is covariant and an implicit reference or identity conversion exists fromAi
toBi
Xi
es contravariante y existe una referencia implícita o una conversión de identidad deBi
aAi
Xi
is contravariant and an implicit reference or identity conversion exists fromBi
toAi
Xi
es invariable y existe una conversión de identidad deAi
aBi
Xi
is invariant and an identity conversion exists fromAi
toBi
Interfaces baseBase interfaces
Una interfaz puede heredar de cero o más tipos de interfaz, que se denominan interfaces base explícitas de la interfaz.An interface can inherit from zero or more interface types, which are called the explicit base interfaces of the interface. Cuando una interfaz tiene una o más interfaces base explícitas, en la declaración de esa interfaz, el identificador de interfaz va seguido de un signo de dos puntos y una lista separada por comas de tipos de interfaz 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
;
En el caso de un tipo de interfaz construido, las interfaces base explícitas se forman tomando las declaraciones de la interfaz base explícita en la declaración de tipos genéricos y sustituyendo por cada type_parameter en la declaración de la interfaz base, la type_argument correspondiente del tipo construido.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.
Las interfaces base explícitas de una interfaz deben ser al menos tan accesibles como la propia interfaz (restricciones de accesibilidad).The explicit base interfaces of an interface must be at least as accessible as the interface itself (Accessibility constraints). Por ejemplo, se trata de un error en tiempo de compilación para especificar una private
internal
interfaz o en el interface_base de una public
interfaz.For example, it is a compile-time error to specify a private
or internal
interface in the interface_base of a public
interface.
Se trata de un error en tiempo de compilación para una interfaz que hereda directa o indirectamente de sí misma.It is a compile-time error for an interface to directly or indirectly inherit from itself.
Las interfaces base de una interfaz son las interfaces base explícitas y sus interfaces base.The base interfaces of an interface are the explicit base interfaces and their base interfaces. En otras palabras, el conjunto de interfaces base es el cierre transitivo completo de las interfaces base explícitas, sus interfaces base explícitas, etc.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. Una interfaz hereda todos los miembros de sus interfaces base.An interface inherits all members of its base interfaces. En el ejemploIn the example
interface IControl
{
void Paint();
}
interface ITextBox: IControl
{
void SetText(string text);
}
interface IListBox: IControl
{
void SetItems(string[] items);
}
interface IComboBox: ITextBox, IListBox {}
las interfaces base de IComboBox
son IControl
, ITextBox
y IListBox
.the base interfaces of IComboBox
are IControl
, ITextBox
, and IListBox
.
En otras palabras, la IComboBox
interfaz anterior hereda miembros y, así SetText
SetItems
como Paint
.In other words, the IComboBox
interface above inherits members SetText
and SetItems
as well as Paint
.
Cada interfaz base de una interfaz debe ser segura para la salida (seguridad de lavarianza).Every base interface of an interface must be output-safe (Variance safety). Una clase o estructura que implementa una interfaz también implementa implícitamente todas las interfaces base de la interfaz.A class or struct that implements an interface also implicitly implements all of the interface's base interfaces.
Cuerpo de la interfazInterface body
El interface_body de una interfaz define los miembros de la interfaz.The interface_body of an interface defines the members of the interface.
interface_body
: '{' interface_member_declaration* '}'
;
Miembros de interfazInterface members
Los miembros de una interfaz son los miembros heredados de las interfaces base y los miembros declarados por la propia interfaz.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
;
Una declaración de interfaz puede declarar cero o más miembros.An interface declaration may declare zero or more members. Los miembros de una interfaz deben ser métodos, propiedades, eventos o indizadores.The members of an interface must be methods, properties, events, or indexers. Una interfaz no puede contener constantes, campos, operadores, constructores de instancias, destructores ni tipos ni una interfaz puede contener miembros estáticos de cualquier tipo.An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.
Todos los miembros de interfaz tienen acceso público de forma implícita.All interface members implicitly have public access. Se trata de un error en tiempo de compilación para que las declaraciones de miembros de interfaz incluyan modificadores.It is a compile-time error for interface member declarations to include any modifiers. En concreto, los miembros de las interfaces no se pueden declarar con los modificadores abstract
,, public
protected
, internal
, private
, virtual
, override
o static
.In particular, interfaces members cannot be declared with the modifiers abstract
, public
, protected
, internal
, private
, virtual
, override
, or static
.
En el ejemploThe 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 una interfaz que contiene uno de los posibles tipos de miembros: un método, una propiedad, un evento y un indexador.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 crea un nuevo espacio de declaración (declaraciones) y el interface_member_declaration s que contiene inmediatamente el interface_declaration introduce nuevos miembros en este espacio de declaración.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. Las siguientes reglas se aplican a interface_member_declaration s:The following rules apply to interface_member_declaration s:
- El nombre de un método debe ser distinto de los nombres de todas las propiedades y eventos declarados en la misma interfaz.The name of a method must differ from the names of all properties and events declared in the same interface. Además, la firma (firmas y sobrecarga) de un método debe ser diferente de las firmas de todos los demás métodos declarados en la misma interfaz, y dos métodos declarados en la misma interfaz no pueden tener firmas que solo difieran en
ref
yout
.In addition, the signature (Signatures and overloading) of a method must differ from the signatures of all other methods declared in the same interface, and two methods declared in the same interface may not have signatures that differ solely byref
andout
. - El nombre de una propiedad o evento debe ser diferente de los nombres de todos los demás miembros declarados en la misma interfaz.The name of a property or event must differ from the names of all other members declared in the same interface.
- La firma de un indexador debe ser diferente de las firmas de los demás indexadores declarados en la misma interfaz.The signature of an indexer must differ from the signatures of all other indexers declared in the same interface.
Los miembros heredados de una interfaz no son específicamente parte del espacio de declaración de la interfaz.The inherited members of an interface are specifically not part of the declaration space of the interface. Por lo tanto, una interfaz puede declarar un miembro con el mismo nombre o signatura que un miembro heredado.Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. Cuando esto ocurre, se dice que el miembro de interfaz derivado oculta el miembro de interfaz base.When this occurs, the derived interface member is said to hide the base interface member. Ocultar un miembro heredado no se considera un error, pero hace que el compilador emita una advertencia.Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. Para suprimir la advertencia, la declaración del miembro de interfaz derivado debe incluir un new
modificador para indicar que el miembro derivado está pensado para ocultar el miembro 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 tema se describe con más detalle en ocultarse a travésde la herencia.This topic is discussed further in Hiding through inheritance.
Si new
se incluye un modificador en una declaración que no oculta un miembro heredado, se emite una advertencia para ese efecto.If a new
modifier is included in a declaration that doesn't hide an inherited member, a warning is issued to that effect. Esta advertencia se suprime quitando el new
modificador.This warning is suppressed by removing the new
modifier.
Tenga en cuenta que los miembros de la clase object
no son, estrictamente hablando, miembros de cualquier interfaz (miembros de lainterfaz).Note that the members in class object
are not, strictly speaking, members of any interface (Interface members). Sin embargo, los miembros de la clase object
están disponibles a través de la búsqueda de miembros en cualquier tipo de interfaz (búsqueda de miembros).However, the members in class object
are available via member lookup in any interface type (Member lookup).
Métodos de interfazInterface methods
Los métodos de interfaz se declaran mediante 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* ';'
;
Los atributos, return_type, identificador y formal_parameter_list de una declaración de método de interfaz tienen el mismo significado que los de una declaración de método en una clase (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). No se permite que una declaración de método de interfaz especifique un cuerpo de método y, por tanto, la declaración termina siempre con un punto y coma.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 un método de interfaz debe ser seguro para la entrada (seguridad de lavarianza) y el tipo de valor devuelto debe ser void
o ser seguro para la salida.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. Además, cada restricción de tipo de clase, restricción de tipo de interfaz y restricción de parámetro de tipo en cualquier parámetro de tipo del método debe ser de seguridad de entrada.Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method must be input-safe.
Estas reglas garantizan que cualquier uso de contravariante o contravariante de la interfaz sigue siendo seguro para tipos.These rules ensure that any covariant or contravariant usage of the interface remains type-safe. Por ejemplo,For example,
interface I<out T> { void M<U>() where U : T; }
no es válido porque el uso de T
como una restricción de parámetro de tipo en U
no es seguro para la entrada.is illegal because the usage of T
as a type parameter constraint on U
is not input-safe.
Si esta restricción no estuviera en su lugar, sería posible infringir la seguridad de tipos de la siguiente manera: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>();
En realidad, se trata de una llamada a C.M<E>
.This is actually a call to C.M<E>
. Pero esa llamada requiere que E
derive de D
, por lo que la seguridad de tipos se infringiría aquí.But that call requires that E
derive from D
, so type safety would be violated here.
Propiedades de la interfazInterface properties
Las propiedades de interfaz se declaran mediante 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' ';'
;
Los atributos, el tipo y el identificador de una declaración de propiedad de interfaz tienen el mismo significado que los de una declaración de propiedad en una clase (propiedades).The attributes, type, and identifier of an interface property declaration have the same meaning as those of a property declaration in a class (Properties).
Los descriptores de acceso de una declaración de propiedad de interfaz corresponden a los descriptores de acceso de una declaración de propiedad de clase (descriptores deacceso), salvo que el cuerpo del descriptor de acceso siempre debe ser un punto y comaThe 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. Por lo tanto, los descriptores de acceso simplemente indican si la propiedad es de lectura y escritura, de solo lectura o de solo escritura.Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only.
El tipo de una propiedad de interfaz debe ser seguro para la salida si hay un descriptor de acceso get y debe ser seguro para la entrada si hay un descriptor de acceso 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 interfazInterface events
Los eventos de interfaz se declaran mediante interface_event_declaration s:Interface events are declared using interface_event_declaration s:
interface_event_declaration
: attributes? 'new'? 'event' type identifier ';'
;
Los atributos, el tipo y el identificador de una declaración de evento de interfaz tienen el mismo significado que los de una declaración de evento en una clase (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).
El tipo de un evento de interfaz debe ser seguro para la entrada.The type of an interface event must be input-safe.
Indexadores de interfazInterface indexers
Los indizadores de interfaz se declaran mediante 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 '}'
;
Los atributos, el tipo y el formal_parameter_list de una declaración de indexador de interfaz tienen el mismo significado que los de una declaración de indexador en una clase (indizadores).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).
Los descriptores de acceso de una declaración de indexador de interfaz corresponden a los descriptores de acceso de una declaración de indizador de clase (indizadores), salvo que el cuerpo del descriptor de acceso siempre debe ser un punto y coma.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. Por lo tanto, los descriptores de acceso indican simplemente si el indizador es de lectura y escritura, de solo lectura o de solo escritura.Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only.
Todos los tipos de parámetros formales de un indizador de interfaz deben ser seguros para la entrada.All the formal parameter types of an interface indexer must be input-safe . Además, cualquier out
tipo de ref
parámetro formal o también debe ser seguro para la salida.In addition, any out
or ref
formal parameter types must also be output-safe. Tenga en cuenta que incluso out
se requiere que los parámetros sean seguros para la entrada, debido a una limitación de la plataforma de ejecución subyacente.Note that even out
parameters are required to be input-safe, due to a limitation of the underlying execution platform.
El tipo de un indizador de interfaz debe ser seguro para la salida si hay un descriptor de acceso get y debe ser seguro para la entrada si hay un descriptor de acceso 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.
Acceso a miembros de interfazInterface member access
Se tiene acceso a los miembros de interfaz a través del acceso a miembros (acceso amiembros) y las expresiones de acceso a indizador (acceso a indizador) del formulario I.M
y I[A]
, donde I
es un tipo de interfaz, M
es un método, propiedad o evento de ese tipo de interfaz, y A
es una lista de argumentos de indizador.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 las interfaces que son estrictamente herencia única (cada interfaz de la cadena de herencia tiene exactamente cero o una interfaz base directa), los efectos de las reglas de búsqueda de miembros (búsqueda de miembros), invocación de métodos (llamadas a métodos) e indexador (acceso a indexador) son exactamente los mismos que para las clases y los Structs: los miembros más derivados ocultan los miembros menos derivados con el mismo nombre o signatura.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. Sin embargo, en el caso de las interfaces de herencia múltiple, pueden producirse ambigüedades cuando dos o más interfaces base no relacionadas declaran miembros con el mismo nombre o signatura.However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. En esta sección se muestran varios ejemplos de esas situaciones.This section shows several examples of such situations. En todos los casos, se pueden usar conversiones explícitas para resolver las ambigüedades.In all cases, explicit casts can be used to resolve the ambiguities.
En el ejemploIn 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
}
}
las dos primeras instrucciones producen errores en tiempo de compilación porque la búsqueda de miembros (búsqueda de miembros) de Count
en IListCounter
es ambigua.the first two statements cause compile-time errors because the member lookup (Member lookup) of Count
in IListCounter
is ambiguous. Como se muestra en el ejemplo, la ambigüedad se resuelve mediante la conversión x
al tipo de interfaz base adecuado.As illustrated by the example, the ambiguity is resolved by casting x
to the appropriate base interface type. Tales conversiones no tienen ningún costo en tiempo de ejecución, simplemente consisten en ver la instancia como un tipo menos derivado en tiempo de compilación.Such casts have no run-time costs—they merely consist of viewing the instance as a less derived type at compile-time.
En el ejemploIn 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
}
}
la invocación n.Add(1)
selecciona IInteger.Add
aplicando las reglas de resolución de sobrecarga de la resolución de sobrecarga.the invocation n.Add(1)
selects IInteger.Add
by applying the overload resolution rules of Overload resolution. De igual forma, la invocación n.Add(1.0)
selecciona IDouble.Add
.Similarly the invocation n.Add(1.0)
selects IDouble.Add
. Cuando se insertan conversiones explícitas, solo hay un método candidato y, por tanto, no hay ambigüedad.When explicit casts are inserted, there is only one candidate method, and thus no ambiguity.
En el ejemploIn 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
}
}
el miembro IBase.F
está oculto por el ILeft.F
miembro.the IBase.F
member is hidden by the ILeft.F
member. La invocación d.F(1)
selecciona ILeft.F
, aunque IBase.F
parece que no está oculto en la ruta de acceso que conduce 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 regla intuitiva para ocultar en interfaces de herencia múltiple es simplemente esto: Si un miembro está oculto en una ruta de acceso, se oculta en todas las rutas de acceso.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. Dado que la ruta de acceso de IDerived
a ILeft
IBase
oculta IBase.F
, el miembro también se oculta en la ruta de acceso de IDerived
a a 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
.
Nombres completos de miembros de interfazFully qualified interface member names
A veces se hace referencia a un miembro de interfaz mediante su nombre completo.An interface member is sometimes referred to by its fully qualified name. El nombre completo de un miembro de interfaz consta del nombre de la interfaz en la que se declara el miembro, seguido de un punto, seguido del nombre del miembro.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. El nombre completo de un miembro hace referencia a la interfaz en la que se declara el miembro.The fully qualified name of a member references the interface in which the member is declared. Por ejemplo, dadas las declaracionesFor example, given the declarations
interface IControl
{
void Paint();
}
interface ITextBox: IControl
{
void SetText(string text);
}
el nombre completo de Paint
es IControl.Paint
y el nombre completo de SetText
es ITextBox.SetText
.the fully qualified name of Paint
is IControl.Paint
and the fully qualified name of SetText
is ITextBox.SetText
.
En el ejemplo anterior, no es posible hacer referencia a Paint
como ITextBox.Paint
.In the example above, it is not possible to refer to Paint
as ITextBox.Paint
.
Cuando una interfaz forma parte de un espacio de nombres, el nombre completo de un miembro de interfaz incluye el nombre del espacio de nombres.When an interface is part of a namespace, the fully qualified name of an interface member includes the namespace name. Por ejemploFor example
namespace System
{
public interface ICloneable
{
object Clone();
}
}
Aquí, el nombre completo del Clone
método es System.ICloneable.Clone
.Here, the fully qualified name of the Clone
method is System.ICloneable.Clone
.
Implementaciones de interfacesInterface implementations
Las interfaces pueden ser implementadas por clases y Structs.Interfaces may be implemented by classes and structs. Para indicar que una clase o estructura implementa directamente una interfaz, el identificador de interfaz se incluye en la lista de clases base de la clase o estructura.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 ejemplo:For example:
interface ICloneable
{
object Clone();
}
interface IComparable
{
int CompareTo(object other);
}
class ListEntry: ICloneable, IComparable
{
public object Clone() {...}
public int CompareTo(object other) {...}
}
Una clase o estructura que implementa directamente una interfaz también implementa directamente todas las interfaces base de la interfaz de forma implícita.A class or struct that directly implements an interface also directly implements all of the interface's base interfaces implicitly. Esto es así incluso si la clase o estructura no enumera explícitamente todas las interfaces base de la lista de clases base.This is true even if the class or struct doesn't explicitly list all base interfaces in the base class list. Por ejemplo:For example:
interface IControl
{
void Paint();
}
interface ITextBox: IControl
{
void SetText(string text);
}
class TextBox: ITextBox
{
public void Paint() {...}
public void SetText(string text) {...}
}
Aquí, la clase TextBox
implementa IControl
y ITextBox
.Here, class TextBox
implements both IControl
and ITextBox
.
Cuando una clase C
implementa directamente una interfaz, todas las clases derivadas de C también implementan la interfaz implícitamente.When a class C
directly implements an interface, all classes derived from C also implement the interface implicitly. Las interfaces base especificadas en una declaración de clase pueden ser tipos de interfaz construidos (tipos construidos).The base interfaces specified in a class declaration can be constructed interface types (Constructed types). Una interfaz base no puede ser un parámetro de tipo por sí misma, aunque puede incluir los parámetros de tipo que se encuentran en el ámbito.A base interface cannot be a type parameter on its own, though it can involve the type parameters that are in scope. En el código siguiente se muestra cómo una clase puede implementar y extender tipos construidos: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> {}
Las interfaces base de una declaración de clase genérica deben cumplir la regla de unicidad descrita en singularidad de las interfaces implementadas.The base interfaces of a generic class declaration must satisfy the uniqueness rule described in Uniqueness of implemented interfaces.
Implementaciones de miembros de interfaz explícitosExplicit interface member implementations
A efectos de la implementación de interfaces, una clase o struct puede declarar implementaciones de miembros de interfaz explícita.For purposes of implementing interfaces, a class or struct may declare explicit interface member implementations. Una implementación explícita de un miembro de interfaz es un método, una propiedad, un evento o una declaración de indexador que hace referencia a un nombre de miembro de interfaz completo.An explicit interface member implementation is a method, property, event, or indexer declaration that references a fully qualified interface member name. Por ejemploFor 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) {...}
}
Aquí IDictionary<int,T>.this
y IDictionary<int,T>.Add
son implementaciones de miembros de interfaz explícitos.Here IDictionary<int,T>.this
and IDictionary<int,T>.Add
are explicit interface member implementations.
En algunos casos, es posible que el nombre de un miembro de interfaz no sea adecuado para la clase de implementación, en cuyo caso el miembro de interfaz se puede implementar utilizando la implementación explícita del miembro de interfaz.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. Una clase que implementa una abstracción de archivo, por ejemplo, podría implementar una Close
función miembro que tenga el efecto de liberar el recurso de archivo e implementar el Dispose
método de la IDisposable
interfaz mediante la implementación explícita del miembro de interfaz: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);
}
}
No es posible tener acceso a una implementación explícita de un miembro de interfaz a través de su nombre completo en una invocación de método, acceso a propiedades o acceso a 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. Solo se puede tener acceso a una implementación de miembro de interfaz explícita a través de una instancia de interfaz y, en ese caso, se hace referencia a ella simplemente por su nombre de miembro.An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.
Se trata de un error en tiempo de compilación para que una implementación explícita de un miembro de interfaz incluya modificadores de acceso, y es un error en tiempo de compilación incluir los modificadores abstract
,, virtual
override
o 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
.
Las implementaciones explícitas de miembros de interfaz tienen distintas características de accesibilidad que otros miembros.Explicit interface member implementations have different accessibility characteristics than other members. Dado que nunca se puede obtener acceso a las implementaciones de miembros de interfaz explícitos mediante su nombre completo en una invocación de método o un acceso de propiedad, se encuentran en un sentido privado.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. Sin embargo, puesto que se puede tener acceso a ellos a través de una instancia de la interfaz, también son públicos.However, since they can be accessed through an interface instance, they are in a sense also public.
Las implementaciones explícitas de miembros de interfaz tienen dos propósitos principales:Explicit interface member implementations serve two primary purposes:
- Dado que no se puede acceder a las implementaciones de miembros de interfaz explícitos a través de instancias de clase o struct, permiten excluir las implementaciones de interfaz de la interfaz pública de una clase o 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. Esto es especialmente útil cuando una clase o estructura implementa una interfaz interna que no es de interés para un consumidor de esa clase o estructura.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.
- Las implementaciones explícitas de miembros de interfaz permiten la desambiguación de los miembros de interfaz con la misma firma.Explicit interface member implementations allow disambiguation of interface members with the same signature. Sin implementaciones explícitas de miembros de interfaz, sería imposible que una clase o struct tenga implementaciones diferentes de miembros de interfaz con la misma signatura y el mismo tipo de valor devuelto, lo que sería imposible para que una clase o struct tenga cualquier implementación en todos los miembros de interfaz con la misma firma pero con distintos tipos de valor devueltos.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 una implementación de miembro de interfaz explícita sea válida, la clase o estructura debe nombrar una interfaz en su lista de clases base que contenga un miembro cuyo nombre completo, tipo y tipos de parámetro coincidan exactamente con los de la implementación explícita del miembro de interfaz.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. Por lo tanto, en la clase siguienteThus, in the following class
class Shape: ICloneable
{
object ICloneable.Clone() {...}
int IComparable.CompareTo(object other) {...} // invalid
}
la declaración de IComparable.CompareTo
genera un error en tiempo de compilación porque IComparable
no aparece en la lista de clases base de Shape
y no es una interfaz 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
. Del mismo modo, en las declaracionesLikewise, in the declarations
class Shape: ICloneable
{
object ICloneable.Clone() {...}
}
class Ellipse: Shape
{
object ICloneable.Clone() {...} // invalid
}
la declaración de ICloneable.Clone
en Ellipse
produce un error en tiempo de compilación porque ICloneable
no aparece explícitamente en la lista de clases 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
.
El nombre completo de un miembro de interfaz debe hacer referencia a la interfaz en la que se declaró el miembro.The fully qualified name of an interface member must reference the interface in which the member was declared. Por lo tanto, en las declaracionesThus, 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) {...}
}
la implementación explícita del miembro de interfaz de Paint
debe escribirse como IControl.Paint
.the explicit interface member implementation of Paint
must be written as IControl.Paint
.
Unicidad de interfaces implementadasUniqueness of implemented interfaces
Las interfaces implementadas por una declaración de tipo genérico deben ser únicas para todos los tipos construidos posibles.The interfaces implemented by a generic type declaration must remain unique for all possible constructed types. Sin esta regla, sería imposible determinar el método correcto al que llamar para determinados tipos construidos.Without this rule, it would be impossible to determine the correct method to call for certain constructed types. Por ejemplo, supongamos que se permitía escribir una declaración de clase genérica como sigue: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() {...}
}
Si se permitiera, sería imposible determinar qué código ejecutar en el caso siguiente: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 si la lista de interfaces de una declaración de tipo genérico es válida, se llevan a cabo los siguientes pasos:To determine if the interface list of a generic type declaration is valid, the following steps are performed:
L
Se trata de la lista de interfaces que se especifican directamente en una clase genérica, struct o declaración de interfazC
.LetL
be the list of interfaces directly specified in a generic class, struct, or interface declarationC
.- Agregue a
L
cualquier interfaz base de las interfaces que ya estén enL
.Add toL
any base interfaces of the interfaces already inL
. - Quite cualquier duplicado de
L
.Remove any duplicates fromL
. - Si se crea un posible tipo construido a partir de
C
, después de que los argumentos de tipo se sustituyen porL
, hace que dos interfaces deL
sean idénticas, la declaración deC
no es válida.If any possible constructed type created fromC
would, after type arguments are substituted intoL
, cause two interfaces inL
to be identical, then the declaration ofC
is invalid. Las declaraciones de restricciones no se tienen en cuenta a la hora de determinar todos los tipos construidos posibles.Constraint declarations are not considered when determining all possible constructed types.
En la declaración de clase X
anterior, la lista L
de interfaces consta de I<U>
y I<V>
.In the class declaration X
above, the interface list L
consists of I<U>
and I<V>
. La declaración no es válida porque cualquier tipo construido con U
y V
que sea del mismo tipo haría que estas dos interfaces sean 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.
Es posible unificar las interfaces especificadas en diferentes niveles de herencia: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() {...}
}
Este código es válido aunque Derived<U,V>
implemente I<U>
y I<V>
.This code is valid even though Derived<U,V>
implements both I<U>
and I<V>
. El código.The code
I<int> x = new Derived<int,int>();
x.F();
invoca el método en Derived
, puesto que se Derived<int,int>
vuelve a implementar de forma eficaz I<int>
(reimplementación de la interfaz).invokes the method in Derived
, since Derived<int,int>
effectively re-implements I<int>
(Interface re-implementation).
Implementación de métodos genéricosImplementation of generic methods
Cuando un método genérico implementa implícitamente un método de interfaz, las restricciones proporcionadas para cada parámetro de tipo de método deben ser equivalentes en ambas declaraciones (después de que los parámetros de tipo de interfaz se reemplacen con los argumentos de tipo adecuados), donde los parámetros de tipo de método se identifican por posiciones ordinales, de izquierda a derecha.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.
Sin embargo, cuando un método genérico implementa explícitamente un método de interfaz, no se permite ninguna restricción en el método de implementación.When a generic method explicitly implements an interface method, however, no constraints are allowed on the implementing method. En su lugar, las restricciones se heredan del método de interfaz.Instead, the constraints are inherited from the interface method
interface I<A,B,C>
{
void F<T>(T t) where T: A;
void G<T>(T t) where T: B;
void H<T>(T t) where T: C;
}
class C: I<object,C,string>
{
public void F<T>(T t) {...} // Ok
public void G<T>(T t) where T: C {...} // Ok
public void H<T>(T t) where T: string {...} // Error
}
El método C.F<T>
implementa implícitamente I<object,C,string>.F<T>
.The method C.F<T>
implicitly implements I<object,C,string>.F<T>
. En este caso, C.F<T>
no es necesario (ni se permite) especificar la restricción, T:object
ya que object
es una restricción implícita en todos los 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. El método C.G<T>
implementa implícitamente I<object,C,string>.G<T>
porque las restricciones coinciden con las de la interfaz, después de que los parámetros de tipo de interfaz se reemplacen por los argumentos de tipo correspondientes.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 restricción para el método C.H<T>
es un error porque los tipos sellados ( string
en este caso) no se pueden usar como restricciones.The constraint for method C.H<T>
is an error because sealed types (string
in this case) cannot be used as constraints. Omitir la restricción también sería un error, ya que las restricciones de las implementaciones de métodos de interfaz implícitas deben coincidir.Omitting the constraint would also be an error since constraints of implicit interface method implementations are required to match. Por lo tanto, es imposible implementar implícitamente I<object,C,string>.H<T>
.Thus, it is impossible to implicitly implement I<object,C,string>.H<T>
. Este método de interfaz solo se puede implementar mediante una implementación explícita de un miembro de interfaz: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);
}
}
En este ejemplo, la implementación de miembro de interfaz explícita invoca un método público que tiene restricciones estrictamente más débiles.In this example, the explicit interface member implementation invokes a public method having strictly weaker constraints. Tenga en cuenta que la asignación de t
a s
es válida, ya que T
hereda una restricción de T:string
, aunque esta restricción no se pueda expresar en el código fuente.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.
Asignación de interfazInterface mapping
Una clase o estructura debe proporcionar implementaciones de todos los miembros de las interfaces que se enumeran en la lista de clases base de la clase o estructura.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. El proceso de buscar implementaciones de miembros de interfaz en una clase o struct de implementación se conoce como asignación de interfaz.The process of locating implementations of interface members in an implementing class or struct is known as interface mapping.
La asignación de interfaz para una clase o struct C
localiza una implementación para cada miembro de cada interfaz especificada en la lista de clases 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
. La implementación de un miembro de interfaz determinado I.M
, donde I
es la interfaz en la que M
se declara el miembro, se determina examinando cada clase o struct S
, empezando por C
y repitiendo cada clase base sucesiva de C
, hasta que se encuentre una coincidencia: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
contiene una declaración de una implementación explícita de un miembro de interfaz que coincide conI
yM
, este miembro es la implementación deI.M
.IfS
contains a declaration of an explicit interface member implementation that matchesI
andM
, then this member is the implementation ofI.M
. - De lo contrario, si
S
contiene una declaración de un miembro público no estático que coincide conM
, este miembro es la implementación deI.M
.Otherwise, ifS
contains a declaration of a non-static public member that matchesM
, then this member is the implementation ofI.M
. Si hay más de un miembro que coincide, no se especifica qué miembro es la implementación deI.M
.If more than one member matches, it is unspecified which member is the implementation ofI.M
. Esta situación solo puede producirse siS
es un tipo construido en el que los dos miembros declarados en el tipo genérico tienen firmas diferentes, pero los argumentos de tipo hacen que sus firmas sean idénticas.This situation can only occur ifS
is a constructed type where the two members as declared in the generic type have different signatures, but the type arguments make their signatures identical.
Se produce un error en tiempo de compilación si no se pueden encontrar implementaciones para todos los miembros de todas las interfaces especificadas en la lista de clases 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
. Tenga en cuenta que los miembros de una interfaz incluyen a los miembros heredados de las interfaces base.Note that the members of an interface include those members that are inherited from base interfaces.
En lo que respecta a la asignación de interfaz, un miembro de clase A
coincide con un miembro de interfaz B
cuando:For purposes of interface mapping, a class member A
matches an interface member B
when:
A
yB
son métodos, y el nombre, el tipo y las listas de parámetros formales deA
yB
son idénticos.A
andB
are methods, and the name, type, and formal parameter lists ofA
andB
are identical.A
yB
son propiedades, el nombre y el tipo deA
yB
son idénticos, yA
tienen los mismos descriptores de acceso queB
(A
se permite tener descriptores de acceso adicionales si no es una implementación de miembro de interfaz explícita).A
andB
are properties, the name and type ofA
andB
are identical, andA
has the same accessors asB
(A
is permitted to have additional accessors if it is not an explicit interface member implementation).A
yB
son eventos, y el nombre y el tipo deA
yB
son idénticos.A
andB
are events, and the name and type ofA
andB
are identical.A
yB
son indizadores, las listas de parámetros de tipo y formales deA
yB
son idénticas, yA
tienen los mismos descriptores de acceso queB
(A
se le permite tener descriptores de acceso adicionales si no es una implementación de miembro de interfaz explícita).A
andB
are indexers, the type and formal parameter lists ofA
andB
are identical, andA
has the same accessors asB
(A
is permitted to have additional accessors if it is not an explicit interface member implementation).
Las implicaciones importantes del algoritmo de asignación de interfaz son:Notable implications of the interface mapping algorithm are:
- Las implementaciones de miembros de interfaz explícitos tienen prioridad sobre otros miembros de la misma clase o estructura al determinar el miembro de clase o de estructura que implementa un miembro de interfaz.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.
- Ninguno de los miembros no públicos ni estáticos participan en la asignación de interfaz.Neither non-public nor static members participate in interface mapping.
En el ejemploIn the example
interface ICloneable
{
object Clone();
}
class C: ICloneable
{
object ICloneable.Clone() {...}
public object Clone() {...}
}
el ICloneable.Clone
miembro de C
se convierte en la implementación de Clone
en ICloneable
porque las implementaciones explícitas de los miembros de interfaz tienen prioridad sobre otros miembros.the ICloneable.Clone
member of C
becomes the implementation of Clone
in ICloneable
because explicit interface member implementations take precedence over other members.
Si una clase o estructura implementa dos o más interfaces que contienen un miembro con el mismo nombre, tipo y tipos de parámetro, es posible asignar cada uno de esos miembros de interfaz a un único miembro de clase o de estructura.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 ejemploFor example
interface IControl
{
void Paint();
}
interface IForm
{
void Paint();
}
class Page: IControl, IForm
{
public void Paint() {...}
}
En este caso, los Paint
métodos de IControl
y IForm
se asignan al Paint
método en Page
.Here, the Paint
methods of both IControl
and IForm
are mapped onto the Paint
method in Page
. También es posible tener implementaciones de miembros de interfaz explícitas independientes para los dos métodos.It is of course also possible to have separate explicit interface member implementations for the two methods.
Si una clase o estructura implementa una interfaz que contiene miembros ocultos, algunos miembros deben implementarse necesariamente mediante implementaciones explícitas de miembros de interfaz.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 ejemploFor example
interface IBase
{
int P { get; }
}
interface IDerived: IBase
{
new int P();
}
Una implementación de esta interfaz requeriría al menos una implementación explícita de un miembro de interfaz y adoptaría uno de los siguientes formatosAn 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() {...}
}
Cuando una clase implementa varias interfaces que tienen la misma interfaz base, solo puede haber una implementación de la interfaz base.When a class implements multiple interfaces that have the same base interface, there can be only one implementation of the base interface. En el ejemploIn 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) {...}
}
no es posible tener implementaciones independientes para el IControl
denominado en la lista de clases base, IControl
heredado por ITextBox
y IControl
heredado 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
. En realidad, no hay ninguna noción de una identidad independiente para estas interfaces.Indeed, there is no notion of a separate identity for these interfaces. En su lugar, las implementaciones de ITextBox
y IListBox
comparten la misma implementación de IControl
y ComboBox
simplemente se considera que implementa tres interfaces,, IControl
ITextBox
y 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
.
Los miembros de una clase base participan en la asignación de interfaz.The members of a base class participate in interface mapping. En el ejemploIn the example
interface Interface1
{
void F();
}
class Class1
{
public void F() {}
public void G() {}
}
class Class2: Class1, Interface1
{
new public void G() {}
}
el método F
de Class1
se usa en Class2
la implementación de de Interface1
.the method F
in Class1
is used in Class2
's implementation of Interface1
.
Herencia de implementación de interfazInterface implementation inheritance
Una clase hereda todas las implementaciones de interfaz proporcionadas por sus clases base.A class inherits all interface implementations provided by its base classes.
Sin volver a implementar explícitamente una interfaz, una clase derivada no puede alterar de ninguna manera las asignaciones de interfaz que hereda de sus clases 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 ejemplo, en las declaracionesFor example, in the declarations
interface IControl
{
void Paint();
}
class Control: IControl
{
public void Paint() {...}
}
class TextBox: Control
{
new public void Paint() {...}
}
el Paint
método en TextBox
oculta el Paint
método en Control
, pero no modifica la asignación de Control.Paint
en IControl.Paint
, y las llamadas a a través de Paint
instancias de clase e instancias de interfaz tendrán los siguientes efectos:the Paint
method in TextBox
hides the Paint
method in Control
, but it does not alter the mapping of Control.Paint
onto IControl.Paint
, and calls to Paint
through class instances and interface instances will have the following effects
Control c = new Control();
TextBox t = new TextBox();
IControl ic = c;
IControl it = t;
c.Paint(); // invokes Control.Paint();
t.Paint(); // invokes TextBox.Paint();
ic.Paint(); // invokes Control.Paint();
it.Paint(); // invokes Control.Paint();
Sin embargo, cuando un método de interfaz se asigna a un método virtual en una clase, es posible que las clases derivadas invaliden el método virtual y modifiquen la implementación de la interfaz.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 ejemplo, volver a escribir las declaraciones anteriores enFor example, rewriting the declarations above to
interface IControl
{
void Paint();
}
class Control: IControl
{
public virtual void Paint() {...}
}
class TextBox: Control
{
public override void Paint() {...}
}
ahora se observarán los siguientes efectos:the following effects will now be observed
Control c = new Control();
TextBox t = new TextBox();
IControl ic = c;
IControl it = t;
c.Paint(); // invokes Control.Paint();
t.Paint(); // invokes TextBox.Paint();
ic.Paint(); // invokes Control.Paint();
it.Paint(); // invokes TextBox.Paint();
Dado que las implementaciones explícitas de los miembros de interfaz no se pueden declarar como virtuales, no es posible invalidar una implementación explícita de un miembro de interfaz.Since explicit interface member implementations cannot be declared virtual, it is not possible to override an explicit interface member implementation. Sin embargo, es absolutamente válido que una implementación de miembro de interfaz explícita llame a otro método, y ese otro método se puede declarar como virtual para permitir que las clases derivadas lo invaliden.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 ejemploFor example
interface IControl
{
void Paint();
}
class Control: IControl
{
void IControl.Paint() { PaintControl(); }
protected virtual void PaintControl() {...}
}
class TextBox: Control
{
protected override void PaintControl() {...}
}
Aquí, las clases derivadas de Control
pueden especializar la implementación de IControl.Paint
invalidando el PaintControl
método.Here, classes derived from Control
can specialize the implementation of IControl.Paint
by overriding the PaintControl
method.
Volver a implementar la interfazInterface re-implementation
Una clase que hereda una implementación de interfaz puede volver a implementar la interfaz incluyéndola en la lista de clases base.A class that inherits an interface implementation is permitted to re-implement the interface by including it in the base class list.
Una nueva implementación de una interfaz sigue exactamente las mismas reglas de asignación de interfaz que una implementación inicial de una interfaz.A re-implementation of an interface follows exactly the same interface mapping rules as an initial implementation of an interface. Por lo tanto, la asignación de interfaz heredada no tiene ningún efecto en la asignación de interfaz establecida para la reimplementación de la interfaz.Thus, the inherited interface mapping has no effect whatsoever on the interface mapping established for the re-implementation of the interface. Por ejemplo, en las declaracionesFor example, in the declarations
interface IControl
{
void Paint();
}
class Control: IControl
{
void IControl.Paint() {...}
}
class MyControl: Control, IControl
{
public void Paint() {}
}
el hecho de que se Control
asigna en IControl.Paint
Control.IControl.Paint
no afecta a la reimplementación en MyControl
, que se asigna a IControl.Paint
MyControl.Paint
.the fact that Control
maps IControl.Paint
onto Control.IControl.Paint
doesn't affect the re-implementation in MyControl
, which maps IControl.Paint
onto MyControl.Paint
.
Las declaraciones de miembros públicos heredados y las declaraciones de miembro de interfaz explícita heredadas participan en el proceso de asignación de interfaz para las interfaces que se han vuelto a implementar.Inherited public member declarations and inherited explicit interface member declarations participate in the interface mapping process for re-implemented interfaces. Por ejemploFor 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() {}
}
Aquí, la implementación de IMethods
en Derived
asigna los métodos de interfaz en Derived.F
, Base.IMethods.G
, Derived.IMethods.H
y 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
.
Cuando una clase implementa una interfaz, también implementa implícitamente todas las interfaces base de esa interfaz.When a class implements an interface, it implicitly also implements all of that interface's base interfaces. Del mismo modo, una nueva implementación de una interfaz también es implícitamente una reimplementación de todas las interfaces base de la interfaz.Likewise, a re-implementation of an interface is also implicitly a re-implementation of all of the interface's base interfaces. Por ejemploFor 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() {...}
}
En este caso, la reimplementación de IDerived
también vuelve a implementar IBase
, y se asigna a IBase.F
D.F
.Here, the re-implementation of IDerived
also re-implements IBase
, mapping IBase.F
onto D.F
.
Clases e interfaces abstractasAbstract classes and interfaces
Al igual que una clase no abstracta, una clase abstracta debe proporcionar implementaciones de todos los miembros de las interfaces que se enumeran en la lista de clases base de la clase.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. Sin embargo, una clase abstracta puede asignar métodos de interfaz a métodos abstractos.However, an abstract class is permitted to map interface methods onto abstract methods. Por ejemploFor example
interface IMethods
{
void F();
void G();
}
abstract class C: IMethods
{
public abstract void F();
public abstract void G();
}
Aquí, la implementación de IMethods
Maps F
y G
en métodos abstractos, que se debe invalidar en clases no abstractas que se derivan 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
.
Tenga en cuenta que las implementaciones explícitas de los miembros de interfaz no pueden ser abstractas, pero las implementaciones de miembros de interfaz explícitas son de curso y permiten llamar a métodos abstractos.Note that explicit interface member implementations cannot be abstract, but explicit interface member implementations are of course permitted to call abstract methods. Por ejemploFor 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();
}
Aquí, las clases no abstractas que derivan de C
deberían reemplazar FF
y GG
, lo que proporciona la implementación 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
.