Qual é a diferença entre implementar uma interface explícita ou implicitamente?

64

No Visual Studio, posso clicar com o botão direito do mouse em uma interface e escolher Implementar Interface ou Implementar Interface Explicitamente.

Captura de tela do 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(); }
    }
}

A única diferença que vejo entre os dois é que o nome da interface é adicionado às propriedades e métodos da interface quando eles são criados, se você optar por implementar a interface explicitamente.

Acho que torna o código um pouco mais legível, pois posso ver de onde vem esse método / propriedade. No entanto, isso faz alguma diferença na maneira como a classe é usada ou compilada? E realmente importa se eu implemento minhas interfaces de forma implícita ou explícita?

Rachel
fonte

Respostas:

51

Confira a resposta principal de Andrew Barrett para "implementação implícita versus interface explícita" no SO .

Basicamente:

  • Implícito: você acessa os métodos e propriedades da interface como se fossem parte da classe.
  • Explícito: você só pode acessar métodos e propriedades ao tratar a classe como a interface implementada.

Exemplos 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

Em termos de "quando" você precisa implementar uma interface explicitamente, é quando sua classe já possui um método com a mesma assinatura que um dos métodos da sua interface ou quando sua classe implementa várias interfaces que compartilham métodos com as mesmas assinaturas mas contratos incompatíveis.

Jalayn
fonte
11
Também achei a implementação explícita útil para ter uma espécie de interface "oculta" com operações inseguras. Também faz com que as chamadas para esses métodos se destaquem mais, o que é bom para coisas inseguras.
Tamás Szelei
Também vale mencionar que há um custo de desempenho no uso de interfaces explícitas, pois ele precisa colocar / desmarcar o objeto sempre que você referenciar a propriedade / método. Devido a isso, é melhor usar interfaces implícitas se possível
Rachel
3
@ Rachel: Pelo que sei, o custo de desempenho se aplica apenas aos tipos de valor.
Groky
8

Há também uma diferença em como você chama o método.

Ao usar uma implementação de interface explícita , você deve usar o tipo de interface para chamar essa implementação específica.

Portanto, ao chamar o código, você precisaria usar uma variável do tipo ITestpara acessar ITest.Id.

O artigo Implementação explícita da interface (Guia de Programação em C #) no MSDN tem um bom exemplo.

Oded
fonte
4

Permite implementar duas interfaces que definem o mesmo método. No entanto, se você implementar explicitamente a interface, os métodos poderão ser acessados ​​somente quando a variável for digitada nessa interface explícita.

Consulte: Tutorial de implementação explícita da interface

unholysampler
fonte
4

EDIT: Não deve fazer a diferença Você não deve fazê-lo, a menos que sua classe implemente duas interfaces com as mesmas propriedades, pois você precisará converter na interface relevante antes de poder acessar o membro:

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);
    }
}

O exemplo de uso é válido quando você implementa explicitamente um membro da interface, mesmo se você estiver usando apenas uma única interface (que eu sempre esqueço: S); portanto, tentaria evitar a implementação explícita sempre que possível, pois ocultará os membros da classe se eles ' não é transmitido para a interface correta (o que é bastante confuso).

Ed James
fonte
3

Com base na resposta de Jalayan,

  • Implícito: você acessa os métodos e propriedades da interface como se fossem parte da classe.
  • Explícito: você só pode acessar métodos e propriedades ao tratar a classe como a interface implementada.

insira a descrição da imagem aqui

Alexander Zaldostanov
fonte