Quelle est la différence entre implémenter une interface explicitement ou implicitement?

64

Dans Visual Studio, je peux cliquer avec le bouton droit sur une interface et choisir d'implémenter une interface ou d'implémenter une interface explicitement.

Capture d'écran 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 seule différence que je vois entre les deux est que le nom de l'interface est ajouté aux propriétés et méthodes de l'interface lors de leur création si vous choisissez d'implémenter l'interface explicitement.

Je trouve que cela rend le code un peu plus lisible puisque je peux voir d'où vient cette méthode / propriété, mais cela fait-il une différence dans la façon dont la classe est utilisée ou compilée? Et est-ce vraiment important si j'implémente mes interfaces implicitement ou explicitement?

Rachel
la source

Réponses:

51

Consultez la réponse principale d'Andrew Barrett pour "l'implémentation d'interfaces implicites ou explicites" sur SO .

Fondamentalement:

  • Implicite: vous accédez aux méthodes et propriétés d'interface comme si elles faisaient partie de la classe.
  • Explicite: vous ne pouvez accéder aux méthodes et aux propriétés que lorsque la classe est traitée comme interface implémentée.

Exemples de code:

Implicite:

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

Explicite:

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

En termes de "quand" vous devez implémenter explicitement une interface, c'est lorsque votre classe a déjà une méthode avec la même signature qu'une des méthodes de votre interface, ou lorsque votre classe implémente plusieurs interfaces qui partagent des méthodes avec les mêmes signatures mais des contrats incompatibles.

Jalayn
la source
1
J'ai également trouvé utile l'implémentation explicite d'avoir une sorte d'interface "cachée" avec des opérations non sécurisées. Il fait également ressortir les appels à ces méthodes, ce qui est une bonne chose pour les objets dangereux.
Tamás Szelei
Il convient également de mentionner que l’utilisation d’interfaces explicites a un coût en termes de performances, puisqu’il faut encapsuler / dé-boxer l’objet chaque fois que vous faites référence à la propriété / méthode. Pour cette raison, il est préférable d'utiliser des interfaces implicites si possible
Rachel
3
@ Rachel: Autant que je sache, le coût de performance ne s'applique qu'aux types de valeur.
Groky
8

Il y a aussi une différence dans la façon dont vous appelez la méthode.

Lorsque vous utilisez une implémentation d'interface explicite , vous devez utiliser le type d'interface pour appeler cette implémentation spécifique.

Donc, dans le code d'appel, vous devez utiliser une variable de type ITestpour pouvoir accéder ITest.Id.

L'article Exploitation d'interface explicite (Guide de programmation C #) sur MSDN en fournit un bon exemple.

Oded
la source
4

Cela vous permet d'implémenter deux interfaces qui définissent la même méthode. Toutefois, si vous implémentez explicitement l'interface, vous ne pouvez accéder aux méthodes que lorsque la variable est typée sur cette interface explicite.

Voir: Didacticiel d'implémentation d'interface explicite

unholysampler
la source
4

EDIT: Cela ne devrait pas faire de différence. Vous ne devriez pas le faire à moins que votre classe implémente deux interfaces avec les mêmes propriétés, car vous devrez transtyper vers l'interface appropriée avant de pouvoir accéder au membre:

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

L'exemple d'utilisation est valable lorsque vous implémentez explicitement un membre d'interface même si vous n'utilisez qu'une seule interface (que j'oublie toujours: S). J'essayerais donc d'éviter autant que possible l'implémentation explicite, car elle masquerait les membres de la classe s'ils ' ne pas jeter à la bonne interface (ce qui est assez déroutant).

Ed James
la source
3

Basé sur la réponse de Jalayan,

  • Implicite: vous accédez aux méthodes et propriétés d'interface comme si elles faisaient partie de la classe.
  • Explicite: vous ne pouvez accéder aux méthodes et aux propriétés que lorsque la classe est traitée comme interface implémentée.

entrez la description de l'image ici

Alexander Zaldostanov
la source