Eu uso a implementação explícita da interface na maioria das vezes. Aqui estão os principais motivos.
A refatoração é mais segura
Ao alterar uma interface, é melhor que o compilador possa verificá-la. Isso é mais difícil com implementações implícitas.
Dois casos comuns vêm à mente:
Adicionando uma função a uma interface, onde uma classe existente que implementa essa interface já possui um método com a mesma assinatura que a nova . Isso pode levar a um comportamento inesperado e me incomodou várias vezes. É difícil "ver" durante a depuração, porque essa função provavelmente não está localizada com os outros métodos de interface do arquivo (o problema de auto-documentação mencionado abaixo).
Removendo uma função de uma interface . Os métodos implementados implicitamente serão código morto subitamente, mas os métodos implementados explicitamente serão capturados por erro de compilação. Mesmo que seja bom manter o código morto, quero ser forçado a revisá-lo e promovê-lo.
É lamentável que o C # não tenha uma palavra-chave que nos obriga a marcar um método como uma implementação implícita, para que o compilador possa fazer verificações extras. Os métodos virtuais não apresentam nenhum dos problemas acima, devido ao uso obrigatório de 'substituir' e 'novo'.
Nota: para interfaces fixas ou que mudam raramente (normalmente das APIs do fornecedor), isso não é um problema. Para minhas próprias interfaces, porém, não posso prever quando / como elas mudarão.
É auto-documentado
Se eu vir 'public bool Execute ()' em uma classe, será necessário um trabalho extra para descobrir que faz parte de uma interface. Alguém provavelmente terá que comentar isso ou colocá-lo em um grupo de outras implementações de interface, tudo em uma região ou comentário de agrupamento dizendo "implementação do ITask". Obviamente, isso só funciona se o cabeçalho do grupo não estiver fora da tela.
Visto que: 'bool ITask.Execute ()' é claro e inequívoco.
Separação clara da implementação da interface
Penso nas interfaces como sendo mais "públicas" que os métodos públicos, porque são criadas para expor apenas um pouco da área superficial do tipo concreto. Eles reduzem o tipo a uma capacidade, um comportamento, um conjunto de características, etc. E na implementação, acho útil manter essa separação.
Enquanto olho o código de uma classe, quando encontro implementações explícitas de interface, meu cérebro muda para o modo "contrato de código". Freqüentemente, essas implementações simplesmente encaminham para outros métodos, mas às vezes realizam verificação extra de estado / parâmetro, conversão de parâmetros recebidos para melhor atender aos requisitos internos ou mesmo tradução para fins de versão (ou seja, várias gerações de interfaces, todas implementadas em implementações comuns).
(Eu percebo que os públicos também são contratos de código, mas as interfaces são muito mais fortes, especialmente em uma base de código orientada por interface em que o uso direto de tipos concretos geralmente é um sinal de código somente interno.)
Relacionado: Razão 2 acima por Jon .
E assim por diante
Além das vantagens já mencionadas em outras respostas aqui:
Problemas
Nem tudo é diversão e felicidade. Existem alguns casos em que fico com implícitos:
- Tipos de valor, porque isso exigirá boxe e menor desempenho. Esta não é uma regra estrita e depende da interface e de como ela deve ser usada. IComparável? Implícito. IFormattable? Provavelmente explícito.
- Interfaces de sistema triviais que possuem métodos frequentemente chamados diretamente (como IDisposable.Dispose).
Além disso, pode ser difícil fazer a transmissão quando, na verdade, você tem o tipo concreto e deseja chamar um método de interface explícito. Eu lido com isso de duas maneiras:
- Adicione públicos e envie os métodos de interface para eles para a implementação. Normalmente acontece com interfaces mais simples ao trabalhar internamente.
- (Meu método preferido) Adicione um
public IMyInterface I { get { return this; } }
(que deve ser incorporado) e ligue foo.I.InterfaceMethod()
. Se várias interfaces que precisam dessa capacidade, expanda o nome além de I (na minha experiência, é raro que eu tenha essa necessidade).