2010-03-26 30 views
26

Aquí está la historia. Creé una interfaz, IVehicle. Implementé explícitamente la interfaz en mi clase, Vehicle.cs.¿Por qué no puedo llamar a métodos dentro de una clase que implementa explícitamente una interfaz?

Aquí es mi interfaz:

Interface IVehicle 
{ 
     int getWheel(); 
} 

aquí es mi clase:

class Vehicle: IVehicle 
{ 

    public int IVehicle.getWheel() 
    { 
     return wheel; 
    } 

    public void printWheel() 
    { 
     Console.WriteLine(getWheel()); 
    } 
} 

en cuenta que getWheel() se implementa de forma explícita. Ahora, cuando trato de llame al ese método dentro de mi clase Vehicle, recibo un error que indica que getWheel() no existe en el contexto actual. ¿Alguien puede ayudarme a entender lo que estoy haciendo mal?

+0

como persona java, me pregunto por qué esto ¿Existe algo complicado? ¿Por qué alguien querría que existiera lo de arriba, qué ventaja gana? –

+0

Especificar un modificador de visibilidad en un miembro explícitamente implementado es un error de sintaxis. El miembro siempre es accesible una vez que su objeto ha sido enviado a su tipo de interfaz. – Trillian

+3

@mP Si está implementando múltiples interfaces con un miembro común, esto le permite suministrar diferentes definiciones de cada interfaz. También se agrega para limpiar intellisense, porque los miembros explícitos no son visibles o utilizables a menos que lo envíes a la interfaz adecuada. –

Respuesta

35

Cuando implementa explícitamente la interfaz, primero debe enviar el objeto a la interfaz, luego puede llamar al método. En otras palabras, el método solo está disponible cuando el método se invoca en el objeto como el tipo de interfaz, no como el tipo concreto.

class Vehicle: IVehicle { 

    public int IVehicle.getWheel() 
    { 
     return wheel; 
    } 

    public void printWheel() 
    { 
     Console.WriteLine(((IVehicle)this).getWheel()); 
    } 
} 

Consulte este reference en MSDN para obtener más información. Aquí está el fragmento relevante:

No es posible acceder a una implementación de miembro de interfaz explícita a través de su nombre completo en una invocación de método, acceso a propiedad o acceso de indexador. Solo se puede acceder 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 simplemente por su nombre de miembro.

Por lo que vale la pena: probablemente este no sea un buen uso de la implementación de interfaz explícita. Normalmente, desea utilizar la implementación explícita cuando tiene una clase que tiene una interfaz completa para operaciones típicas, pero también implementa una interfaz que puede reemplazar algunas de esas operaciones. El ejemplo canónico es una clase File que implementa IDisposable. Tendría un método Close(), pero se le solicitará que implemente Dispose(). Al tratar como File, usaría Open/Close. Sin embargo, cuando se abre en una instrucción using, se tratará como IDisposable y se llamará al Dispose. En este caso Dispose simplemente llama al Close. No necesariamente quiere exponer Dispose como parte de la implementación File ya que el mismo comportamiento está disponible en Close.

+0

Gracias. Solo lo hice para probarme a mí mismo que podía hacerlo. Hasta este punto, el libro que estoy usando no dio ninguna razón que indique la necesidad de implementar explícitamente la interfaz. – tyrone302

+0

Otro ejemplo común de esto es en los archivos '.Designer' generados de una aplicación de winforms. Cada control se inicializa entre un par de métodos '.BeginInit()' y '.EndInit()', pero esas llamadas se realizan * después * de convertir el control en 'ISupportInitialize'. – kdbanman

11

Según MSDN:

Es posible implementar un miembro de interfaz explícitamente de creación de un miembro de clase que sólo se llama a través de la interfaz de, y es específico a esa interfaz.

Y en el C# language specifications:

No es posible acceder a una aplicación de interfaz explícita miembro de totalmente a través de su nombre calificado en una invocación de método, acceso a la propiedad, o el acceso indexador. Una implementación miembro de interfaz explícita solo se puede tener acceso a a través de una instancia de interfaz, y es en ese caso al que se hace referencia simplemente por su nombre de miembro .

Para acceder a este miembro, primero puede convertir la clase a la interfaz y luego acceder a ella.

3

Para evitar un montón de aburrido proyecta en su clase, se podría crear un puntero como el tipo de interfaz

public class Foo : IBar 
{ 
    readonly IBar bar; 
    public Foo() 
    { 
     bar = this; 
    } 
} 

y luego llamar a los miembros usando bar.

Cuestiones relacionadas