¿Cuál es la diferencia entre implementar una interfaz explícita o implícitamente?

64

En Visual Studio, puedo hacer clic derecho en una interfaz y elegir Implementar interfaz, o Implementar interfaz explícitamente.

Captura de pantalla de Visual Studio

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

La única diferencia que veo entre los dos es que el nombre de la interfaz se agrega a las propiedades y métodos de la interfaz cuando se crean si elige Implementar la interfaz explícitamente.

Creo que hace que el código sea un poco más legible ya que puedo ver de dónde proviene ese método / propiedad, sin embargo, ¿esto hace alguna diferencia en cómo se usa o compila la clase? ¿Y realmente importa si implemento mis interfaces implícita o explícitamente?

Rachel
fuente

Respuestas:

51

Consulte la respuesta principal de Andrew Barrett para "implementación de interfaz implícita frente a explícita" en SO .

Básicamente:

  • Implícito: accede a los métodos y propiedades de la interfaz como si fueran parte de la clase.
  • Explícito: solo puede acceder a métodos y propiedades cuando trata la clase como la interfaz implementada.

Ejemplos de código:

Implícito:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

Explícito:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

En términos de "cuándo" debe implementar una interfaz explícitamente, es cuando su clase ya tiene un método con la misma firma que uno de los métodos de su interfaz, o cuando su clase implementa varias interfaces que comparten métodos con las mismas firmas pero contratos incompatibles.

Jalayn
fuente
1
También encontré que la implementación explícita es útil para tener una especie de interfaz "oculta" con operaciones inseguras. También hace que las llamadas a esos métodos se destaquen más, lo que es bueno para las cosas inseguras.
Tamás Szelei
También vale la pena mencionar que el uso de interfaces explícitas conlleva un costo de rendimiento, ya que debe encajonar / desempaquetar el objeto cada vez que haga referencia a la propiedad / método. Debido a esto, es mejor usar interfaces implícitas si es posible
Rachel
3
@Rachel: Que yo sepa, el costo de rendimiento solo se aplica a los tipos de valor.
Groky
8

También hay una diferencia en cómo se llama al método.

Al usar una implementación de interfaz explícita , debe usar el tipo de interfaz para llamar a esa implementación específica.

Entonces, en el código de llamada, necesitaría usar una variable de tipo ITestpara acceder ITest.Id.

El artículo Implementación de interfaz explícita (Guía de programación de C #) en MSDN tiene un buen ejemplo.

Oded
fuente
4

Le permite implementar dos interfaces que definen el mismo método. Sin embargo, si implementa explícitamente la interfaz, solo se puede acceder a los métodos cuando la variable se escribe en esa interfaz explícita.

Ver: Tutorial de implementación de interfaz explícita

muestreador
fuente
4

EDITAR: No debería hacer una diferencia No debería hacerlo a menos que su clase implemente dos interfaces con las mismas propiedades, ya que tendrá que enviar a la interfaz relevante antes de poder acceder al miembro:

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

El uso de ejemplo se mantiene cuando implementa explícitamente un miembro de la interfaz, incluso si solo usa una única interfaz (que siempre olvido: S), por lo que trataría de evitar la implementación explícita siempre que sea posible, ya que ocultará a los miembros de la clase si ' No se envía a la interfaz correcta (lo cual es bastante confuso).

Ed James
fuente
3

Según la respuesta de Jalayan,

  • Implícito: accede a los métodos y propiedades de la interfaz como si fueran parte de la clase.
  • Explícito: solo puede acceder a métodos y propiedades cuando trata la clase como la interfaz implementada.

ingrese la descripción de la imagen aquí

Alexander Zaldostanov
fuente