2010-03-26 8 views
26

Voici l'histoire. J'ai créé une interface, IVehicle. J'ai explicitement implémenté l'interface dans ma classe, Vehicle.cs.Pourquoi ne puis-je pas appeler des méthodes dans une classe qui implémente explicitement une interface?

Voici mon interface:

Interface IVehicle 
{ 
     int getWheel(); 
} 

ici est ma classe:

class Vehicle: IVehicle 
{ 

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

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

Notez que getWheel() est explicitement mis en œuvre. Maintenant, quand j'essaye appeler cette méthode dans ma classe de véhicule, je reçois une erreur indiquant que getWheel() n'existe pas dans le contexte actuel. Quelqu'un peut-il m'aider à comprendre ce que je fais de mal?

+0

comme une personne java, je me demande pourquoi ce chose alambiquée existe? Pourquoi quelqu'un voudrait-il que ce qui précède existe, quel avantage cela procure-t-il? –

+0

La spécification d'un modificateur de visibilité sur un membre explicitement implémenté est une erreur de syntaxe. Le membre est toujours accessible une fois que votre objet a été casté sur votre type d'interface. – Trillian

+3

@mP Si vous implémentez plusieurs interfaces avec un membre commun, cela vous permet de fournir différentes définitions par interface. En outre, il ajoute à nettoyer intellisense, parce que les membres explicites ne sont pas visibles ou utilisables, sauf si vous lancez à l'interface appropriée. –

Répondre

35

Lorsque vous implémentez explicitement l'interface, vous devez d'abord convertir l'objet en interface, puis vous pouvez appeler la méthode. En d'autres termes, la méthode n'est disponible que lorsque la méthode est appelée sur l'objet en tant que type d'interface, et non en tant que type concret.

class Vehicle: IVehicle { 

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

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

Voir ce reference à MSDN pour plus d'informations. Voici l'extrait pertinent:

Il est impossible d'accéder à une implémentation membre d'interface explicite par son nom complet dans un appel de méthode, l'accès à la propriété ou l'accès indexeur. Une implémentation de membre d'interface explicite ne peut être accédée qu'à travers une instance d'interface, et est dans ce cas référencée simplement par son nom de membre.

Pour ce que cela vaut - ce n'est probablement pas une utilisation particulièrement bonne de l'implémentation d'interface explicite. En règle générale, vous souhaitez utiliser une implémentation explicite lorsque vous disposez d'une classe disposant d'une interface complète pour les opérations classiques, mais implémente également une interface qui peut remplacer certaines de ces opérations. L'exemple canonique est une classe File qui implémente IDisposable. Il aurait une méthode Close(), mais serait nécessaire pour implémenter Dispose(). En traitant comme File vous utiliseriez Open/Close. Lorsqu'elle est ouverte dans une instruction using, elle la traite comme IDisposable et appelle le Dispose. Dans ce cas Dispose appelle simplement Close. Vous ne voulez pas nécessairement exposer Dispose dans le cadre de l'implémentation File puisque le même comportement est disponible à partir de Close.

+0

Merci. Je l'ai seulement fait pour me prouver que je pouvais le faire. À ce stade, le livre que j'utilise n'a donné aucune raison indiquant la nécessité d'implémenter explicitement l'interface. – tyrone302

+0

Un autre exemple courant de ceci est dans les fichiers '.Designer' générés d'une application winforms. Chaque contrôle est initialisé entre une paire de méthodes '.BeginInit()' et '.EndInit()', mais ces appels sont tous faits * après * le passage du contrôle à 'ISupportInitialize'. – kdbanman

11

Selon MSDN:

Il est possible de mettre en œuvre un élément de création explicitement un membre de la classe l'interface qui est seulement appelé par l'interface et est spécifique à cette interface.

Et dans le C# language specifications:

Il est impossible d'accéder à un membre d'interface explicite mise en œuvre via sa nom qualifié dans un appel de méthode, accès à la propriété ou l'accès indexeur. Une implémentation de l'interface explicite ne peut être accédée que par via une instance d'interface, et est dans ce cas référencée simplement par son nom de membre.

Pour accéder à ce membre, vous pouvez d'abord convertir la classe en interface, puis y accéder.

3

Pour éviter beaucoup de ennuyeux moulages de votre classe, vous pouvez créer un pointeur comme le type d'interface

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

Et puis appeler les membres en utilisant bar.

Questions connexes