71 votes

Erreur de compilation : "Le modificateur 'public' n'est pas valide pour cet élément" lors de l'implémentation explicite de l'interface

Je reçois cette erreur lors de la création d'un public sur une classe pour implémenter explicitement la méthode interface . J'ai une solution de contournement : en supprimant l'implémentation explicite de la fonction PrintName méthode. Mais je suis surpris de voir pourquoi je reçois cette erreur.

Quelqu'un peut-il expliquer cette erreur ?

Code pour la bibliothèque :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Test.Lib1
{

    public class Customer : i1 
    {
        public string i1.PrintName() //Error Here...
        {
            return this.GetType().Name + " called from interface i1";
        }
    }

    public interface i1
    {
        string PrintName();
    }

    interface i2
    {
        string PrintName();
    }
}

Code pour l'application de test de la console :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Test.Lib1;

namespace ca1.Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Customer customer = new Customer();
            Console.WriteLine(customer.PrintName());

            //i1 i1o = new Customer();
            //Console.WriteLine(i1o.printname());

            //i2 i2o = new Customer();
            //Console.WriteLine(i2o.printname());

        }
    }
}

84voto

Henk Holterman Points 153608

Lorsque vous utilisez explicite implémentation d'une interface, les membres sont contraints à quelque chose de plus restreint que privé dans la classe elle-même. Et lorsque le modificateur d'accès est forcé, vous ne pouvez pas en ajouter un.

De la même façon, dans l'interface elle-même, tous les membres sont public . Si vous essayez d'ajouter un modificateur à l'intérieur d'une interface, vous obtiendrez une erreur similaire.

Pourquoi les membres explicites sont-ils (très) privés ? Considérez :

interface I1 { void M(); }
interface I2 { void M(); }

class C : I1, I2
{
    void I1.M() { ... }
    void I2.M() { ... }
}

C c = new C();
c.M();         // Error, otherwise: which one?
(c as I1).M(); // Ok, no ambiguity. 

Si ces méthodes étaient publiques, vous auriez un conflit de noms qui ne pourrait pas être résolu par les règles normales de surcharge.

Pour la même raison que vous ne pouvez même pas appeler M() de l'intérieur d'un class C membre. Vous devrez lancer this à une interface spécifique en premier lieu pour éviter la même ambiguïté.

class C : I1, I2
{
   ...
   void X() 
   {  
     M();             // error, which one? 
     ((I1)this).M();  // OK 
   }
}

1 votes

(c as I1).M() ; // pas de problème C'est correct, mais si vous voulez accéder à la méthode M en dehors de l'assambly, elle n'est pas accessible ?

0 votes

@Lalit, il est accessible partout où I1 est accessible. Aussi dans d'autres assemblées.

0 votes

L'interface I1 est accessible de l'extérieur mais la méthode M pour la classe C n'est pas accessible de l'extérieur. Vérifiez le navigateur de classe, il est également marqué comme privé.

14voto

hackerhasid Points 3781

http://msdn.microsoft.com/en-us/library/aa288461(VS.71).aspx : Lorsqu'un membre est explicitement implémenté, on ne peut pas y accéder via une instance de la classe, mais uniquement via une instance de l'interface.

Customer customer = new Customer();

Console.WriteLine(customer.PrintName());

Viole ceci

9voto

Andrew Bezzub Points 8794

Vous ne pouvez pas utiliser de modificateurs d'accès lorsque vous implémentez explicitement une interface. Le membre sera de toute façon lié à l'interface, il n'est donc pas nécessaire de spécifier un modificateur d'accès, car tous les membres de l'interface sont toujours publics, et tous les membres implémentés explicitement ne sont accessibles que par le biais d'un membre de type interface (voir la réponse de statichippo par exemple).

0 votes

"C'est une erreur de compilation pour une implémentation explicite d'un membre d'interface d'inclure des modificateurs d'accès, et c'est une erreur de compilation d'inclure les modificateurs abstract, virtual, override, ou static." Documentation pertinente ( msdn.microsoft.com/fr/us/library/aa664591%28v=VS.71%29.aspx ).

-1voto

Ankur Kumar Points 1

Il s'agit d'une implémentation explicite, la portée par défaut des membres de l'interface est publique, alors qu'elle est privée dans le cas d'une classe, ergo, il n'est pas nécessaire d'utiliser le modificateur Public car lorsque nous appelons cette méthode, elle sera appelée avec la référence de l'interface uniquement.

Selon " Mise en œuvre explicite de l'interface MSDN "les fonctions qui implémentent des interfaces explicites ne sont jamais explicitement définies comme publiques. Elles sont publiques par défaut. Il serait inutile de les définir autrement.

-3voto

Sumit Agrawal Points 683

Si nous voulons utiliser une implémentation implicite pour l'exemple ci-dessus, le code suivant sera utilisé.

    interface I1 { void M(); }
interface I2 { void M(); }

class C : I1, I2
{
    public void M() { ... }
}

C c = new C();
c.M();  // Ok, no ambiguity. Because both Interfaces gets implemented with one    method definition.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X